[banshee] Show the track context menu in artist/album lists



commit 26fb7038d617232d0212c4cffd62a58443129654
Author: Gabriel Burt <gabriel burt gmail com>
Date:   Mon Nov 8 20:32:37 2010 -0600

    Show the track context menu in artist/album lists
    
    This lets you right-click an artist or album and 'Add to Play Queue',
    and most of the other normal track context-menu actions.  Focusing a
    browser also makes the action keybindings affect the artist or album;
    pressing 'q' after clicking an album will queue the entire album.
    
    Fixes bgo#528948

 .../Banshee.Gnome/Banshee.GnomeBackend/Brasero.cs  |    9 +-
 .../Banshee.Playlist/AbstractPlaylistSource.cs     |    4 +-
 .../Banshee.Playlist/PlaylistSource.cs             |    4 +-
 .../Banshee.Sources/DatabaseSource.cs              |   52 +++++---
 .../Banshee.Sources/ITrackModelSource.cs           |    5 +-
 .../Banshee.Sources/PrimarySource.cs               |   34 +----
 .../Banshee.Collection.Gui/TrackFilterListView.cs  |   41 +++++-
 .../Banshee.Gui.TrackEditor/TrackEditorDialog.cs   |   33 +++--
 .../Banshee.Gui/TrackActions.cs                    |  138 +++++++++++++++-----
 .../Banshee.AudioCd/AudioCdSource.cs               |    5 +-
 .../Banshee.InternetArchive/DetailsSource.cs       |    4 +-
 .../Banshee.InternetRadio/InternetRadioSource.cs   |   12 +-
 .../Banshee.LastfmStreaming/StationSource.cs       |    5 +-
 .../Banshee.PlayQueue/PlayQueueActions.cs          |    4 +-
 .../Banshee.PlayQueue/PlayQueueSource.cs           |   15 ++-
 15 files changed, 229 insertions(+), 136 deletions(-)
---
diff --git a/src/Backends/Banshee.Gnome/Banshee.GnomeBackend/Brasero.cs b/src/Backends/Banshee.Gnome/Banshee.GnomeBackend/Brasero.cs
index 1afb39e..206c3d3 100644
--- a/src/Backends/Banshee.Gnome/Banshee.GnomeBackend/Brasero.cs
+++ b/src/Backends/Banshee.Gnome/Banshee.GnomeBackend/Brasero.cs
@@ -88,10 +88,11 @@ namespace Banshee.GnomeBackend
                 return;
             }
 
+            var track_actions = ServiceManager.Get<InterfaceActionService> ().TrackActions;
             StringBuilder file_args = new StringBuilder ();
             file_args.Append ("-a");
 
-            foreach (TrackInfo track in source.TrackModel.SelectedItems) {
+            foreach (TrackInfo track in track_actions.SelectedTracks) {
                 if (track.Uri.IsLocalPath) {
                     file_args.AppendFormat (" \"{0}\"", track.Uri.AbsolutePath.Replace ("\"", "\\\""));
                 }
@@ -115,8 +116,8 @@ namespace Banshee.GnomeBackend
 
         private void UpdateActions ()
         {
-            InterfaceActionService uia_service = ServiceManager.Get<InterfaceActionService> ();
-            Gtk.Action action = uia_service.TrackActions["BurnDiscAction"];
+            var track_actions = ServiceManager.Get<InterfaceActionService> ().TrackActions;
+            Gtk.Action action = track_actions["BurnDiscAction"];
 
             bool visible = false;
             bool sensitive = false;
@@ -128,7 +129,7 @@ namespace Banshee.GnomeBackend
                     visible = true;
                 }
 
-                sensitive = source.TrackModel.Selection.Count > 0;
+                sensitive = track_actions.Selection.Count > 0;
             }
 
             action.Sensitive = sensitive;
diff --git a/src/Core/Banshee.Services/Banshee.Playlist/AbstractPlaylistSource.cs b/src/Core/Banshee.Services/Banshee.Playlist/AbstractPlaylistSource.cs
index d66d05c..1d36d8e 100644
--- a/src/Core/Banshee.Services/Banshee.Playlist/AbstractPlaylistSource.cs
+++ b/src/Core/Banshee.Services/Banshee.Playlist/AbstractPlaylistSource.cs
@@ -209,10 +209,10 @@ namespace Banshee.Playlist
         }
 
         // Have our parent handle deleting tracks
-        public override void DeleteSelectedTracks ()
+        public override void DeleteTracks (DatabaseTrackListModel model, Selection selection)
         {
             if (Parent is PrimarySource) {
-                (Parent as PrimarySource).DeleteSelectedTracksFromChild (this);
+                (Parent as PrimarySource).DeleteTracks (model, selection);
             }
         }
 
diff --git a/src/Core/Banshee.Services/Banshee.Playlist/PlaylistSource.cs b/src/Core/Banshee.Services/Banshee.Playlist/PlaylistSource.cs
index 3255f9d..0b9efa4 100644
--- a/src/Core/Banshee.Services/Banshee.Playlist/PlaylistSource.cs
+++ b/src/Core/Banshee.Services/Banshee.Playlist/PlaylistSource.cs
@@ -244,10 +244,10 @@ namespace Banshee.Playlist
             AddTrack (track.TrackId);
         }
 
-        public override bool AddSelectedTracks (Source source)
+        public override bool AddSelectedTracks (Source source, Selection selection)
         {
             if (Parent == null || source == Parent || source.Parent == Parent) {
-                return base.AddSelectedTracks (source);
+                return base.AddSelectedTracks (source, selection);
             } else {
                 // Adding from a different primary source, so add to our primary source first
                 //PrimarySource primary = Parent as PrimarySource;
diff --git a/src/Core/Banshee.Services/Banshee.Sources/DatabaseSource.cs b/src/Core/Banshee.Services/Banshee.Sources/DatabaseSource.cs
index 1879453..fed5a0a 100644
--- a/src/Core/Banshee.Services/Banshee.Sources/DatabaseSource.cs
+++ b/src/Core/Banshee.Services/Banshee.Sources/DatabaseSource.cs
@@ -432,58 +432,62 @@ namespace Banshee.Sources
             RemoveTrack (track_model.IndexOf (track));
         }
 
-        public virtual void RemoveSelectedTracks ()
+        public void RemoveTracks (Selection selection)
         {
-            RemoveSelectedTracks (track_model);
+            RemoveTracks (track_model, selection);
         }
 
-        public virtual void RemoveSelectedTracks (DatabaseTrackListModel model)
+        public void RemoveTracks (DatabaseTrackListModel model, Selection selection)
         {
-            WithTrackSelection (model, RemoveTrackRange);
+            WithTrackSelection (model, selection, RemoveTrackRange);
             OnTracksRemoved ();
         }
 
-        public virtual void DeleteSelectedTracks ()
+        public void DeleteTracks (Selection selection)
         {
-            DeleteSelectedTracks (track_model);
+            DeleteTracks (track_model, selection);
         }
 
-        protected virtual void DeleteSelectedTracks (DatabaseTrackListModel model)
+        public virtual void DeleteTracks (DatabaseTrackListModel model, Selection selection)
         {
             if (model == null)
                 return;
 
-            WithTrackSelection (model, DeleteTrackRange);
+            WithTrackSelection (model, selection, DeleteTrackRange);
             OnTracksDeleted ();
         }
 
-        public virtual bool AddSelectedTracks (Source source)
+        public bool AddSelectedTracks (Source source)
         {
-            if (!AcceptsInputFromSource (source))
+            var track_src = source as ITrackModelSource;
+            return AddSelectedTracks (source, track_src == null ? null : track_src.TrackModel.Selection);
+        }
+
+        public virtual bool AddSelectedTracks (Source source, Selection selection)
+        {
+            if (!AcceptsInputFromSource (source) || selection.Count == 0)
                 return false;
 
             DatabaseTrackListModel model = (source as ITrackModelSource).TrackModel as DatabaseTrackListModel;
             if (model == null) {
                 return false;
             }
-            WithTrackSelection (model, AddTrackRange);
+
+            WithTrackSelection (model, selection, AddTrackRange);
             OnTracksAdded ();
             OnUserNotifyUpdated ();
             return true;
         }
 
-        public virtual bool AddAllTracks (Source source)
+        public bool AddAllTracks (Source source)
         {
-            if (!AcceptsInputFromSource (source) || source.Count == 0)
-                return false;
-
-            DatabaseTrackListModel model = (source as ITrackModelSource).TrackModel as DatabaseTrackListModel;
-            lock (model) {
-                AddTrackRange (model, new RangeCollection.Range (0, source.Count));
+            var track_src = source as ITrackModelSource;
+            if (track_src != null) {
+                var selection = new Selection () { MaxIndex = track_src.TrackModel.Selection.MaxIndex };
+                selection.SelectAll ();
+                return AddSelectedTracks (source, selection);
             }
-            OnTracksAdded ();
-            OnUserNotifyUpdated ();
-            return true;
+            return false;
         }
 
         public virtual void RateSelectedTracks (int rating)
@@ -649,7 +653,11 @@ namespace Banshee.Sources
 
         protected void WithTrackSelection (DatabaseTrackListModel model, TrackRangeHandler handler)
         {
-            Selection selection = model.Selection;
+            WithTrackSelection (model, model.Selection, handler);
+        }
+
+        protected void WithTrackSelection (DatabaseTrackListModel model, Selection selection, TrackRangeHandler handler)
+        {
             if (selection.Count == 0)
                 return;
 
diff --git a/src/Core/Banshee.Services/Banshee.Sources/ITrackModelSource.cs b/src/Core/Banshee.Services/Banshee.Sources/ITrackModelSource.cs
index 4bc88a3..4bdb627 100644
--- a/src/Core/Banshee.Services/Banshee.Sources/ITrackModelSource.cs
+++ b/src/Core/Banshee.Services/Banshee.Sources/ITrackModelSource.cs
@@ -32,6 +32,7 @@ using System.Collections.Generic;
 using NDesk.DBus;
 
 using Banshee.Collection;
+using Hyena.Collections;
 
 namespace Banshee.Sources
 {
@@ -42,8 +43,8 @@ namespace Banshee.Sources
         void Reload ();
         bool HasDependencies { get; }
 
-        void RemoveSelectedTracks ();
-        void DeleteSelectedTracks ();
+        void RemoveTracks (Selection selection);
+        void DeleteTracks (Selection selection);
 
         bool CanAddTracks { get; }
         bool CanRemoveTracks { get; }
diff --git a/src/Core/Banshee.Services/Banshee.Sources/PrimarySource.cs b/src/Core/Banshee.Services/Banshee.Sources/PrimarySource.cs
index 08d8ce1..b4861fc 100644
--- a/src/Core/Banshee.Services/Banshee.Sources/PrimarySource.cs
+++ b/src/Core/Banshee.Services/Banshee.Sources/PrimarySource.cs
@@ -444,14 +444,6 @@ namespace Banshee.Sources
             );
         }
 
-        public void DeleteSelectedTracksFromChild (DatabaseSource source)
-        {
-            if (source.Parent != this)
-                return;
-
-            DeleteSelectedTracks (source.TrackModel as DatabaseTrackListModel);
-        }
-
         public void DeleteAllTracks (AbstractPlaylistSource source)
         {
             if (source.PrimarySource != this) {
@@ -462,20 +454,20 @@ namespace Banshee.Sources
             if (source.Count < 1)
                 return;
 
+            var list = CachedList<DatabaseTrackInfo>.CreateFromModel (source.DatabaseTrackModel);
             ThreadAssist.SpawnFromMain (delegate {
-                CachedList<DatabaseTrackInfo> list = CachedList<DatabaseTrackInfo>.CreateFromModel (source.DatabaseTrackModel);
                 DeleteTrackList (list);
             });
         }
 
-        protected override void DeleteSelectedTracks (DatabaseTrackListModel model)
+        public override void DeleteTracks (DatabaseTrackListModel model, Selection selection)
         {
             if (model == null || model.Count < 1) {
                 return;
             }
 
+            var list = CachedList<DatabaseTrackInfo>.CreateFromModelAndSelection (model, selection);
             ThreadAssist.SpawnFromMain (delegate {
-                CachedList<DatabaseTrackInfo> list = CachedList<DatabaseTrackInfo>.CreateFromModelSelection (model);
                 DeleteTrackList (list);
             });
         }
@@ -558,7 +550,7 @@ namespace Banshee.Sources
                 && !(source.Parent is Banshee.Library.LibrarySource);
         }
 
-        public override bool AddSelectedTracks (Source source)
+        public override bool AddSelectedTracks (Source source, Selection selection)
         {
             if (!AcceptsInputFromSource (source))
                 return false;
@@ -566,23 +558,7 @@ namespace Banshee.Sources
             DatabaseTrackListModel model = (source as ITrackModelSource).TrackModel as DatabaseTrackListModel;
 
             // Store a snapshot of the current selection
-            CachedList<DatabaseTrackInfo> cached_list = CachedList<DatabaseTrackInfo>.CreateFromModelSelection (model);
-            if (ThreadAssist.InMainThread) {
-                System.Threading.ThreadPool.QueueUserWorkItem (AddTrackList, cached_list);
-            } else {
-                AddTrackList (cached_list);
-            }
-            return true;
-        }
-
-        public override bool AddAllTracks (Source source)
-        {
-            if (!AcceptsInputFromSource (source) || source.Count == 0) {
-                return false;
-            }
-
-            DatabaseTrackListModel model = (source as ITrackModelSource).TrackModel as DatabaseTrackListModel;
-            CachedList<DatabaseTrackInfo> cached_list = CachedList<DatabaseTrackInfo>.CreateFromModel (model);
+            CachedList<DatabaseTrackInfo> cached_list = CachedList<DatabaseTrackInfo>.CreateFromModelAndSelection (model, selection);
             if (ThreadAssist.InMainThread) {
                 System.Threading.ThreadPool.QueueUserWorkItem (AddTrackList, cached_list);
             } else {
diff --git a/src/Core/Banshee.ThickClient/Banshee.Collection.Gui/TrackFilterListView.cs b/src/Core/Banshee.ThickClient/Banshee.Collection.Gui/TrackFilterListView.cs
index d0cc8ab..ca6ccff 100644
--- a/src/Core/Banshee.ThickClient/Banshee.Collection.Gui/TrackFilterListView.cs
+++ b/src/Core/Banshee.ThickClient/Banshee.Collection.Gui/TrackFilterListView.cs
@@ -48,10 +48,15 @@ namespace Banshee.Collection.Gui
 
             ForceDragSourceSet = true;
             HeaderVisible = false;
+            HasTrackContextMenu = true;
 
             RowActivated += OnRowActivated;
+
+            SelectionProxy.Changed += OnSelectionChanged;
         }
 
+        public bool HasTrackContextMenu { get; set; }
+
         protected override void OnModelReloaded ()
         {
             base.OnModelReloaded ();
@@ -64,27 +69,47 @@ namespace Banshee.Collection.Gui
             ServiceManager.PlaybackController.First ();
         }
 
-        // TODO add context menu for artists/albums...probably need a Banshee.Gui/ArtistActions.cs file.  Should
-        // make TrackActions.cs more generic with regards to the TrackSelection stuff, using the new properties
-        // set on the sources themselves that give us access to the IListView<T>.
-        /*protected override bool OnPopupMenu ()
+        protected override bool OnPopupMenu ()
         {
-            ServiceManager.Get<InterfaceActionService> ().TrackActions["TrackContextMenuAction"].Activate ();
+            if (!HasTrackContextMenu || (Selection is SelectAllSelection && Selection.AllSelected)) {
+                return false;
+            }
+
+            TrackActions["TrackContextMenuAction"].Activate ();
             return true;
-        }*/
+        }
 
         protected override bool OnFocusInEvent(Gdk.EventFocus evnt)
         {
-            ServiceManager.Get<InterfaceActionService> ().TrackActions.SuppressSelectActions ();
+            if (HasTrackContextMenu) {
+                TrackActions.FilterFocused = true;
+            }
             return base.OnFocusInEvent(evnt);
         }
 
         protected override bool OnFocusOutEvent(Gdk.EventFocus evnt)
         {
-            ServiceManager.Get<InterfaceActionService> ().TrackActions.UnsuppressSelectActions ();
+            if (HasTrackContextMenu) {
+                var focus = ServiceManager.Get<GtkElementsService> ().PrimaryWindow.Focus;
+                if (focus != this) {
+                    TrackActions.FilterFocused = false;
+                }
+            }
             return base.OnFocusOutEvent(evnt);
         }
 
+        private void OnSelectionChanged (object o, EventArgs args)
+        {
+            if (HasTrackContextMenu && TrackActions.FilterFocused) {
+                TrackActions.UpdateActions ();
+            }
+        }
+
+        private TrackActions track_actions;
+        private TrackActions TrackActions {
+            get { return track_actions ?? (track_actions = ServiceManager.Get<InterfaceActionService> ().TrackActions); }
+        }
+
 #region Drag and Drop
 
         protected override void OnDragSourceSet ()
diff --git a/src/Core/Banshee.ThickClient/Banshee.Gui.TrackEditor/TrackEditorDialog.cs b/src/Core/Banshee.ThickClient/Banshee.Gui.TrackEditor/TrackEditorDialog.cs
index 22dcc3a..949489b 100644
--- a/src/Core/Banshee.ThickClient/Banshee.Gui.TrackEditor/TrackEditorDialog.cs
+++ b/src/Core/Banshee.ThickClient/Banshee.Gui.TrackEditor/TrackEditorDialog.cs
@@ -47,6 +47,8 @@ using Banshee.Configuration.Schema;
 using Banshee.Widgets;
 using Banshee.Gui.Dialogs;
 using Banshee.Collection.Gui;
+using Hyena.Data;
+using Selection=Hyena.Collections.Selection;
 
 namespace Banshee.Gui.TrackEditor
 {
@@ -86,18 +88,18 @@ namespace Banshee.Gui.TrackEditor
 
         public event EventHandler Navigated;
 
-        private TrackEditorDialog (TrackListModel model, EditorMode mode)
-            : this (model, mode, false)
+        private TrackEditorDialog (TrackListModel model, Selection selection, EditorMode mode)
+            : this (model, selection, mode, false)
         {
         }
 
-        private TrackEditorDialog (TrackListModel model, EditorMode mode, bool readonlyTabs) : base (
+        private TrackEditorDialog (TrackListModel model, Selection selection, EditorMode mode, bool readonlyTabs) : base (
             mode == EditorMode.Edit ? Catalog.GetString ("Track Editor") : Catalog.GetString ("Track Properties"))
         {
             readonly_tabs = readonlyTabs;
             this.mode = mode;
 
-            LoadTrackModel (model);
+            LoadTrackModel (model, selection);
 
             if (mode == EditorMode.Edit || readonly_tabs) {
                 WidthRequest = 525;
@@ -383,14 +385,15 @@ namespace Banshee.Gui.TrackEditor
         private Dictionary<TrackInfo, EditorTrackInfo> edit_map = new Dictionary<TrackInfo, EditorTrackInfo> ();
         private int current_track_index;
 
-        protected void LoadTrackModel (TrackListModel model)
+        protected void LoadTrackModel (TrackListModel model, Selection selection)
         {
             DatabaseTrackListModel db_model = model as DatabaseTrackListModel;
             if (db_model != null) {
-                db_selection = CachedList<DatabaseTrackInfo>.CreateFromModelSelection (db_model);
+                db_selection = CachedList<DatabaseTrackInfo>.CreateFromModelAndSelection (db_model, selection);
             } else {
                 memory_selection = new List<TrackInfo> ();
-                foreach (TrackInfo track in model.SelectedItems) {
+                var items = new ModelSelection<TrackInfo> (model, selection);
+                foreach (TrackInfo track in items) {
                     memory_selection.Add (track);
                 }
             }
@@ -626,24 +629,24 @@ namespace Banshee.Gui.TrackEditor
 
 #region Static Helpers
 
-        public static void RunEdit (TrackListModel model)
+        public static void RunEdit (TrackListModel model, Selection selection)
         {
-            Run (model, EditorMode.Edit);
+            Run (model, selection, EditorMode.Edit);
         }
 
-        public static void RunView (TrackListModel model, bool readonlyTabs)
+        public static void RunView (TrackListModel model, Selection selection, bool readonlyTabs)
         {
-            Run (model, EditorMode.View, readonlyTabs);
+            Run (model, selection, EditorMode.View, readonlyTabs);
         }
 
-        public static void Run (TrackListModel model, EditorMode mode)
+        public static void Run (TrackListModel model, Selection selection, EditorMode mode)
         {
-            Run (new TrackEditorDialog (model, mode));
+            Run (new TrackEditorDialog (model, selection, mode));
         }
 
-        private static void Run (TrackListModel model, EditorMode mode, bool readonlyTabs)
+        private static void Run (TrackListModel model, Selection selection, EditorMode mode, bool readonlyTabs)
         {
-            Run (new TrackEditorDialog (model, mode, readonlyTabs));
+            Run (new TrackEditorDialog (model, selection, mode, readonlyTabs));
         }
 
         private static void Run (TrackEditorDialog track_editor)
diff --git a/src/Core/Banshee.ThickClient/Banshee.Gui/TrackActions.cs b/src/Core/Banshee.ThickClient/Banshee.Gui/TrackActions.cs
index 4f68208..77af10b 100644
--- a/src/Core/Banshee.ThickClient/Banshee.Gui/TrackActions.cs
+++ b/src/Core/Banshee.ThickClient/Banshee.Gui/TrackActions.cs
@@ -45,6 +45,7 @@ using Banshee.Widgets;
 using Banshee.Gui;
 using Banshee.Gui.Dialogs;
 using Banshee.Gui.Widgets;
+using Hyena.Data;
 
 namespace Banshee.Gui
 {
@@ -53,13 +54,52 @@ namespace Banshee.Gui
         private RatingActionProxy rating_proxy;
 
         private static readonly string [] require_selection_actions = new string [] {
-            "TrackContextMenuAction", "TrackPropertiesAction", "AddToPlaylistAction",
+            "TrackPropertiesAction", "AddToPlaylistAction",
             "RemoveTracksAction", "RemoveTracksFromLibraryAction", "OpenContainingFolderAction",
             "DeleteTracksFromDriveAction", "RateTracksAction", "SelectNoneAction", "PlayTrack"
         };
 
+        private static readonly string [] disable_for_filter_actions = new string [] {
+            "SelectAllAction", "SelectNoneAction", "SearchMenuAction",
+            // FIXME should be able to do this, just need to implement it
+            "RateTracksAction"
+        };
+
+        private Hyena.Collections.Selection filter_selection = new Hyena.Collections.Selection ();
+
+        private bool filter_focused;
+        public bool FilterFocused {
+            get { return filter_focused; }
+            set {
+                if (filter_focused == value)
+                    return;
+
+                filter_focused = value;
+                if (value) {
+                    Selection = filter_selection;
+                    SuppressSelectActions ();
+                } else {
+                    Selection = current_source.TrackModel.Selection;
+                    UnsuppressSelectActions ();
+                }
+
+                UpdateActions ();
+                OnSelectionChanged ();
+            }
+        }
+
         public event EventHandler SelectionChanged;
 
+        public Hyena.Collections.Selection Selection { get; private set; }
+
+        public ModelSelection<TrackInfo> SelectedTracks {
+            get {
+                return FilterFocused
+                    ? new ModelSelection<TrackInfo> (current_source.TrackModel, Selection)
+                    : current_source.TrackModel.SelectedItems;
+            }
+        }
+
         public TrackActions () : base ("Track")
         {
             Add (new ActionEntry [] {
@@ -142,6 +182,8 @@ namespace Banshee.Gui
         private ITrackModelSource current_source;
         private void HandleActiveSourceChanged (SourceEventArgs args)
         {
+            FilterFocused = false;
+
             if (current_source != null && current_source.TrackModel != null) {
                 current_source.TrackModel.Selection.Changed -= HandleSelectionChanged;
                 current_source = null;
@@ -151,6 +193,7 @@ namespace Banshee.Gui
             if (new_source != null) {
                 new_source.TrackModel.Selection.Changed += HandleSelectionChanged;
                 current_source = new_source;
+                Selection = new_source.TrackModel.Selection;
             }
 
             ThreadAssist.ProxyToMain (UpdateActions);
@@ -192,7 +235,7 @@ namespace Banshee.Gui
 #region Utility Methods
 
         private bool select_actions_suppressed = false;
-        public void SuppressSelectActions ()
+        private void SuppressSelectActions ()
         {
             if (!select_actions_suppressed) {
                 this ["SelectAllAction"].DisconnectAccelerator ();
@@ -201,7 +244,7 @@ namespace Banshee.Gui
             }
         }
 
-        public void UnsuppressSelectActions ()
+        private void UnsuppressSelectActions ()
         {
             if (select_actions_suppressed) {
                 this ["SelectAllAction"].ConnectAccelerator ();
@@ -210,7 +253,7 @@ namespace Banshee.Gui
             }
         }
 
-        private void UpdateActions ()
+        public void UpdateActions ()
         {
             Source source = ServiceManager.SourceManager.ActiveSource;
             if (source == null) {
@@ -223,16 +266,27 @@ namespace Banshee.Gui
 
             var track_source = source as ITrackModelSource;
             if (track_source != null) {
-                var selection = track_source.TrackModel.Selection;
+                if (FilterFocused) {
+                    if (Selection == filter_selection) {
+                        filter_selection.MaxIndex = track_source.TrackModel.Selection.MaxIndex;
+                        filter_selection.SelectAll ();
+                    } else {
+                        Log.Error ("Filter focused, but selection is not filter selection!");
+                        Console.WriteLine (System.Environment.StackTrace);
+                    }
+                }
+
+                var selection = Selection;
+                int count = selection.Count;
                 Sensitive = Visible = true;
-                bool has_selection = selection.Count > 0;
-                bool has_single_selection = selection.Count == 1;
+                bool has_selection = count > 0;
+                bool has_single_selection = count == 1;
 
                 foreach (string action in require_selection_actions) {
                     this[action].Sensitive = has_selection;
                 }
 
-                UpdateActions (source.CanSearch, has_single_selection,
+                UpdateActions (source.CanSearch && !FilterFocused, has_single_selection,
                    "SearchMenuAction", "SearchForSameArtistAction", "SearchForSameAlbumAction"
                 );
 
@@ -257,6 +311,10 @@ namespace Banshee.Gui
                     this["DeleteTracksFromDriveAction"].Label = String.Format (
                         Catalog.GetString ("_Delete From \"{0}\""), primary_source.StorageName);
                 }
+
+                if (FilterFocused) {
+                    UpdateActions (false, false, disable_for_filter_actions);
+                }
             } else {
                 Sensitive = Visible = false;
             }
@@ -268,8 +326,8 @@ namespace Banshee.Gui
                 int rating = 0;
 
                 // If there is only one track, get the preset rating
-                if (current_source.TrackModel.Selection.Count == 1) {
-                    foreach (TrackInfo track in current_source.TrackModel.SelectedItems) {
+                if (Selection.Count == 1) {
+                    foreach (TrackInfo track in SelectedTracks) {
                         rating = track.Rating;
                     }
                 }
@@ -296,7 +354,16 @@ namespace Banshee.Gui
         private void OnTrackContextMenu (object o, EventArgs args)
         {
             ResetRating ();
-            ShowContextMenu ("/TrackContextMenu");
+            UpdateActions ();
+            var menu = ShowContextMenu ("/TrackContextMenu");
+            if (menu != null) {
+                menu.SelectionDone += OnMenuSelectionDone;
+            }
+        }
+
+        private void OnMenuSelectionDone (object o, EventArgs args)
+        {
+            (o as Menu).SelectionDone -= OnMenuSelectionDone;
         }
 
         private bool RunSourceOverrideHandler (string sourceOverrideHandler)
@@ -319,15 +386,14 @@ namespace Banshee.Gui
             if (current_source != null && !RunSourceOverrideHandler ("TrackPropertiesActionHandler")) {
                 var s = current_source as Source;
                 var readonly_tabs = s != null && !s.HasEditableTrackProperties;
-                TrackEditor.TrackEditorDialog.RunView (current_source.TrackModel,
-                                                       readonly_tabs);
+                TrackEditor.TrackEditorDialog.RunView (current_source.TrackModel, Selection, readonly_tabs);
             }
         }
 
         private void OnTrackEditor (object o, EventArgs args)
         {
             if (current_source != null && !RunSourceOverrideHandler ("TrackEditorActionHandler")) {
-                TrackEditor.TrackEditorDialog.RunEdit (current_source.TrackModel);
+                TrackEditor.TrackEditorDialog.RunEdit (current_source.TrackModel, Selection);
             }
         }
 
@@ -335,7 +401,7 @@ namespace Banshee.Gui
         {
             var source = ServiceManager.SourceManager.ActiveSource as ITrackModelSource;
             if (source != null) {
-                var track = source.TrackModel [source.TrackModel.Selection.FocusedIndex];
+                var track = source.TrackModel [FilterFocused ? 0 : source.TrackModel.Selection.FocusedIndex];
                 if (track.HasAttribute (TrackMediaAttributes.ExternalResource)) {
                     System.Diagnostics.Process.Start (track.Uri);
                 } else {
@@ -394,29 +460,32 @@ namespace Banshee.Gui
             PlaylistSource playlist = new PlaylistSource (Catalog.GetString ("New Playlist"), ActivePrimarySource);
             playlist.Save ();
             playlist.PrimarySource.AddChildSource (playlist);
-            ThreadAssist.SpawnFromMain (delegate {
-                playlist.AddSelectedTracks (ActiveSource);
-            });
+            AddToPlaylist (playlist);
         }
 
         private void OnAddToExistingPlaylist (object o, EventArgs args)
         {
-            ThreadAssist.SpawnFromMain (delegate {
-                ((PlaylistMenuItem)o).Playlist.AddSelectedTracks (ActiveSource);
-            });
+            AddToPlaylist (((PlaylistMenuItem)o).Playlist);
+        }
+
+        private void AddToPlaylist (PlaylistSource playlist)
+        {
+            if (!FilterFocused) {
+                playlist.AddSelectedTracks (ActiveSource);
+            } else {
+                playlist.AddAllTracks (ActiveSource);
+            }
         }
 
         private void OnRemoveTracks (object o, EventArgs args)
         {
             ITrackModelSource source = ActiveSource as ITrackModelSource;
 
-            if (!ConfirmRemove (source, false, source.TrackModel.Selection.Count))
+            if (!ConfirmRemove (source, false, Selection.Count))
                 return;
 
             if (source != null && source.CanRemoveTracks) {
-                ThreadAssist.SpawnFromMain (delegate {
-                    source.RemoveSelectedTracks ();
-                });
+                source.RemoveTracks (Selection);
             }
         }
 
@@ -427,12 +496,12 @@ namespace Banshee.Gui
             if (source != null) {
                 LibrarySource library = source.Parent as LibrarySource;
                 if (library != null) {
-                    if (!ConfirmRemove (library, false, source.TrackModel.Selection.Count)) {
+                    if (!ConfirmRemove (library, false, Selection.Count)) {
                         return;
                     }
 
                     ThreadAssist.SpawnFromMain (delegate {
-                        library.RemoveSelectedTracks (source.TrackModel as DatabaseTrackListModel);
+                        library.RemoveTracks (source.TrackModel as DatabaseTrackListModel, Selection);
                     });
                 }
             }
@@ -441,16 +510,16 @@ namespace Banshee.Gui
         private void OnOpenContainingFolder (object o, EventArgs args)
         {
             var source = ActiveSource as ITrackModelSource;
+            if (source == null || source.TrackModel == null)
+                return;
 
-            if (source == null ||
-                source.TrackModel == null ||
-                source.TrackModel.SelectedItems == null ||
-                source.TrackModel.SelectedItems.Count != 1) {
+            var items = SelectedTracks;
+            if (items == null || items.Count != 1) {
                 Log.Error ("Could not open containing folder");
                 return;
             }
 
-            foreach (var track in source.TrackModel.SelectedItems) {
+            foreach (var track in items) {
                 var path = System.IO.Path.GetDirectoryName (track.Uri.AbsolutePath);
                 if (Banshee.IO.Directory.Exists (path)) {
                     System.Diagnostics.Process.Start (path);
@@ -477,14 +546,15 @@ namespace Banshee.Gui
         {
             ITrackModelSource source = ActiveSource as ITrackModelSource;
 
-            if (!ConfirmRemove (source, true, source.TrackModel.Selection.Count))
+            if (!ConfirmRemove (source, true, Selection.Count))
                 return;
 
             if (source != null && source.CanDeleteTracks) {
-                source.DeleteSelectedTracks ();
+                source.DeleteTracks (Selection);
             }
         }
 
+        // FIXME filter
         private void OnRateTracks (object o, EventArgs args)
         {
             ThreadAssist.SpawnFromMain (delegate {
diff --git a/src/Extensions/Banshee.AudioCd/Banshee.AudioCd/AudioCdSource.cs b/src/Extensions/Banshee.AudioCd/Banshee.AudioCd/AudioCdSource.cs
index ab14347..2466b60 100644
--- a/src/Extensions/Banshee.AudioCd/Banshee.AudioCd/AudioCdSource.cs
+++ b/src/Extensions/Banshee.AudioCd/Banshee.AudioCd/AudioCdSource.cs
@@ -41,6 +41,7 @@ using Banshee.Collection.Database;
 
 using Gtk;
 using Banshee.Gui;
+using Selection = Hyena.Collections.Selection;
 
 namespace Banshee.AudioCd
 {
@@ -298,11 +299,11 @@ namespace Banshee.AudioCd
             disc_model.Reload ();
         }
 
-        public void RemoveSelectedTracks ()
+        public void RemoveTracks (Selection selection)
         {
         }
 
-        public void DeleteSelectedTracks ()
+        public void DeleteTracks (Selection selection)
         {
         }
 
diff --git a/src/Extensions/Banshee.InternetArchive/Banshee.InternetArchive/DetailsSource.cs b/src/Extensions/Banshee.InternetArchive/Banshee.InternetArchive/DetailsSource.cs
index 1d7c434..de6966f 100644
--- a/src/Extensions/Banshee.InternetArchive/Banshee.InternetArchive/DetailsSource.cs
+++ b/src/Extensions/Banshee.InternetArchive/Banshee.InternetArchive/DetailsSource.cs
@@ -199,8 +199,8 @@ namespace Banshee.InternetArchive
 
         public bool HasDependencies { get { return false; } }
 
-        public void RemoveSelectedTracks () {}
-        public void DeleteSelectedTracks () {}
+        public void RemoveTracks (Selection selection) {}
+        public void DeleteTracks (Selection selection) {}
 
         public bool ConfirmRemoveTracks { get { return false; } }
 
diff --git a/src/Extensions/Banshee.InternetRadio/Banshee.InternetRadio/InternetRadioSource.cs b/src/Extensions/Banshee.InternetRadio/Banshee.InternetRadio/InternetRadioSource.cs
index 240869e..da05bf0 100644
--- a/src/Extensions/Banshee.InternetRadio/Banshee.InternetRadio/InternetRadioSource.cs
+++ b/src/Extensions/Banshee.InternetRadio/Banshee.InternetRadio/InternetRadioSource.cs
@@ -83,16 +83,14 @@ namespace Banshee.InternetRadio
             Properties.Set<string> ("SearchEntryDescription", Catalog.GetString ("Search your stations"));
             Properties.SetString ("TrackEditorActionLabel", Catalog.GetString ("Edit Station"));
             Properties.Set<InvokeHandler> ("TrackEditorActionHandler", delegate {
-                ITrackModelSource active_track_model_source =
-                    (ITrackModelSource) ServiceManager.SourceManager.ActiveSource;
-
-                if (active_track_model_source.TrackModel.SelectedItems == null ||
-                    active_track_model_source.TrackModel.SelectedItems.Count <= 0) {
+                var track_actions = ServiceManager.Get<InterfaceActionService> ().TrackActions;
+                var tracks = track_actions.SelectedTracks;
+                if (tracks == null || tracks.Count <= 0) {
                     return;
                 }
 
-                foreach (TrackInfo track in active_track_model_source.TrackModel.SelectedItems) {
-                    DatabaseTrackInfo station_track = track as DatabaseTrackInfo;
+                foreach (var track in tracks) {
+                    var station_track = track as DatabaseTrackInfo;
                     if (station_track != null) {
                         EditStation (station_track);
                         return;
diff --git a/src/Extensions/Banshee.LastfmStreaming/Banshee.LastfmStreaming/StationSource.cs b/src/Extensions/Banshee.LastfmStreaming/Banshee.LastfmStreaming/StationSource.cs
index 0262e0c..270208b 100644
--- a/src/Extensions/Banshee.LastfmStreaming/Banshee.LastfmStreaming/StationSource.cs
+++ b/src/Extensions/Banshee.LastfmStreaming/Banshee.LastfmStreaming/StationSource.cs
@@ -50,6 +50,7 @@ using Banshee.Collection;
 using Banshee.ServiceStack;
 using Banshee.PlaybackController;
 using Banshee.Lastfm;
+using Selection=Hyena.Collections.Selection;
 
 namespace Banshee.LastfmStreaming.Radio
 {
@@ -476,11 +477,11 @@ namespace Banshee.LastfmStreaming.Radio
             track_model.Reload ();
         }
 
-        public void RemoveSelectedTracks ()
+        public void RemoveTracks (Selection selection)
         {
         }
 
-        public void DeleteSelectedTracks ()
+        public void DeleteTracks (Selection selection)
         {
             throw new Exception ("Should not call DeleteSelectedTracks on StationSource");
         }
diff --git a/src/Extensions/Banshee.PlayQueue/Banshee.PlayQueue/PlayQueueActions.cs b/src/Extensions/Banshee.PlayQueue/Banshee.PlayQueue/PlayQueueActions.cs
index b5a126b..c7e5b4e 100644
--- a/src/Extensions/Banshee.PlayQueue/Banshee.PlayQueue/PlayQueueActions.cs
+++ b/src/Extensions/Banshee.PlayQueue/Banshee.PlayQueue/PlayQueueActions.cs
@@ -36,6 +36,7 @@ using Hyena;
 using Banshee.MediaEngine;
 using Banshee.ServiceStack;
 using Banshee.Sources;
+using Banshee.Gui;
 
 namespace Banshee.PlayQueue
 {
@@ -163,7 +164,8 @@ namespace Banshee.PlayQueue
 
         private void AddSelectedToPlayQueue (QueueMode mode)
         {
-            playqueue.AddSelectedTracks (ServiceManager.SourceManager.ActiveSource, mode);
+            var track_actions = ServiceManager.Get<InterfaceActionService> ().TrackActions;
+            playqueue.AddSelectedTracks (ServiceManager.SourceManager.ActiveSource, track_actions.Selection, mode);
         }
 
         private void OnClearPlayQueue (object o, EventArgs args)
diff --git a/src/Extensions/Banshee.PlayQueue/Banshee.PlayQueue/PlayQueueSource.cs b/src/Extensions/Banshee.PlayQueue/Banshee.PlayQueue/PlayQueueSource.cs
index 6b41b89..ae5ef0c 100644
--- a/src/Extensions/Banshee.PlayQueue/Banshee.PlayQueue/PlayQueueSource.cs
+++ b/src/Extensions/Banshee.PlayQueue/Banshee.PlayQueue/PlayQueueSource.cs
@@ -320,19 +320,26 @@ namespace Banshee.PlayQueue
 
 #endregion
 
-        public override bool AddSelectedTracks (Source souce)
+        public override bool AddSelectedTracks (Source source, Selection selection)
         {
-            return AddSelectedTracks (souce, QueueMode.Normal);
+            return AddSelectedTracks (source, selection, QueueMode.Normal);
         }
 
         public bool AddSelectedTracks (Source source, QueueMode mode)
         {
+            return AddSelectedTracks (source, null, mode);
+        }
+
+        public bool AddSelectedTracks (Source source, Selection selection, QueueMode mode)
+        {
             if ((Parent == null || source == Parent || source.Parent == Parent) && AcceptsInputFromSource (source)) {
                 DatabaseTrackListModel model = (source as ITrackModelSource).TrackModel as DatabaseTrackListModel;
                 if (model == null) {
                     return false;
                 }
 
+                selection = selection ?? model.Selection;
+
                 long view_order = CalculateViewOrder (mode);
                 long max_view_order = MaxViewOrder;
                 long current_view_order = CurrentTrackViewOrder;
@@ -344,10 +351,10 @@ namespace Banshee.PlayQueue
                     index = TrackModel.IndexOf (current_track);
                 }
 
-                WithTrackSelection (model, shuffler.RecordInsertions);
+                WithTrackSelection (model, selection, shuffler.RecordInsertions);
 
                 // Add the tracks to the end of the queue.
-                WithTrackSelection (model, AddTrackRange);
+                WithTrackSelection (model, selection, AddTrackRange);
 
                 if (mode != QueueMode.Normal) {
                     ShiftForAddedAfter (view_order, max_view_order);



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