[banshee/art-caching] Allow setting cover art via DnD and context menu



commit 513d13d811b13ff426ae2af37a7aeb623b915940
Author: Gabriel Burt <gabriel burt gmail com>
Date:   Fri Dec 4 19:41:59 2009 -0800

    Allow setting cover art via DnD and context menu
    
    You can drag images onto the bottom-left cover art (if shown), or the
    image shown in the toolbar, or to the image shown in the track metadata
    editor.  You can also right click on any of those to delete the current
    image or choose a new one via a file dialog.  Fixes BGO #336350

 src/Core/Banshee.Core/Banshee.Base/CoverArtSpec.cs |   13 ++
 .../FileSystemQueryJob.cs                          |    8 +-
 .../Banshee.Collection.Gui/ArtworkManager.cs       |   16 +++
 .../Banshee.Collection.Gui/CoverArtEditor.cs       |  140 +++++++++++++++++---
 .../Banshee.Gui.TrackEditor/TrackEditorDialog.cs   |   12 ++-
 .../Banshee.Gui.Widgets/TrackInfoDisplay.cs        |   10 +-
 6 files changed, 166 insertions(+), 33 deletions(-)
---
diff --git a/src/Core/Banshee.Core/Banshee.Base/CoverArtSpec.cs b/src/Core/Banshee.Core/Banshee.Base/CoverArtSpec.cs
index bfe7f0a..2a9793f 100644
--- a/src/Core/Banshee.Core/Banshee.Base/CoverArtSpec.cs
+++ b/src/Core/Banshee.Core/Banshee.Base/CoverArtSpec.cs
@@ -68,6 +68,19 @@ namespace Banshee.Base
                 : Path.Combine (RootPath, Path.Combine (size.ToString (), String.Format ("{0}.jpg", aaid)));
         }
 
+        // When importing new cover art, if not JPEGs, then we use the .cover extension
+        // as a signal to the ArtworkManager that it needs to convert it to JPEG first.
+        public static string GetPathForNewFile (string aaid, string imagePath)
+        {
+            string extension = "cover";
+            if (imagePath.EndsWith ("jpg", true, System.Globalization.CultureInfo.InvariantCulture) ||
+                imagePath.EndsWith ("jpeg", true, System.Globalization.CultureInfo.InvariantCulture)) {
+                extension = "jpg";
+            }
+
+            return System.IO.Path.ChangeExtension (GetPath (aaid), extension);
+        }
+
         public static string CreateArtistAlbumId (string artist, string album)
         {
             return CreateArtistAlbumId (artist, album, false);
diff --git a/src/Core/Banshee.Services/Banshee.Metadata.FileSystem/FileSystemQueryJob.cs b/src/Core/Banshee.Services/Banshee.Metadata.FileSystem/FileSystemQueryJob.cs
index 87d482a..09cf2eb 100644
--- a/src/Core/Banshee.Services/Banshee.Metadata.FileSystem/FileSystemQueryJob.cs
+++ b/src/Core/Banshee.Services/Banshee.Metadata.FileSystem/FileSystemQueryJob.cs
@@ -111,14 +111,8 @@ namespace Banshee.Metadata.FileSystem
 
             if (best_file != null) {
                 try {
-                    string extension = "cover";
-                    if (best_file.EndsWith ("jpg", true, System.Globalization.CultureInfo.InvariantCulture) ||
-                        best_file.EndsWith ("jpeg", true, System.Globalization.CultureInfo.InvariantCulture)) {
-                        extension = "jpg";
-                    }
-
                     // Copy the file to the cover art directory
-                    SaveAtomically (Path.ChangeExtension (CoverArtSpec.GetPath (Track.ArtworkId), extension), Banshee.IO.File.OpenRead (new SafeUri (best_file)));
+                    SaveAtomically (CoverArtSpec.GetPathForNewFile (Track.ArtworkId, best_file), Banshee.IO.File.OpenRead (new SafeUri (best_file)));
 
                     // Send the new StreamTag
                     StreamTag tag = new StreamTag ();
diff --git a/src/Core/Banshee.ThickClient/Banshee.Collection.Gui/ArtworkManager.cs b/src/Core/Banshee.ThickClient/Banshee.Collection.Gui/ArtworkManager.cs
index 5c7b2ff..90b5577 100644
--- a/src/Core/Banshee.ThickClient/Banshee.Collection.Gui/ArtworkManager.cs
+++ b/src/Core/Banshee.ThickClient/Banshee.Collection.Gui/ArtworkManager.cs
@@ -200,6 +200,22 @@ namespace Banshee.Collection.Gui
             return null;
         }
 
+        public void ClearCacheFor (string id)
+        {
+            // Clear from the in-memory cache
+            foreach (int size in scale_caches.Keys) {
+                scale_caches[size].Remove (id);
+            }
+
+            // And delete from disk
+            foreach (int size in CachedSizes ()) {
+                var uri = new SafeUri (CoverArtSpec.GetPathForSize (id, size));
+                if (File.Exists (uri)) {
+                    File.Delete (uri);
+                }
+            }
+        }
+
         public void AddCachedSize (int size)
         {
             cacheable_cover_sizes.Add (size);
diff --git a/src/Core/Banshee.ThickClient/Banshee.Collection.Gui/CoverArtEditor.cs b/src/Core/Banshee.ThickClient/Banshee.Collection.Gui/CoverArtEditor.cs
index 09aa33e..45010b9 100644
--- a/src/Core/Banshee.ThickClient/Banshee.Collection.Gui/CoverArtEditor.cs
+++ b/src/Core/Banshee.ThickClient/Banshee.Collection.Gui/CoverArtEditor.cs
@@ -27,6 +27,7 @@
 //
 
 using System;
+using System.Text;
 using System.Collections.Generic;
 
 using Mono.Unix;
@@ -53,31 +54,134 @@ namespace Banshee.Collection.Gui
     {
         public static Widget For (Widget widget, Func<int, int, bool> is_sensitive, Func<TrackInfo> get_track, System.Action on_updated)
         {
-            var box = new EventBox ();
-            box.Child = widget;
-
-            Gtk.Drag.SourceSet (box, Gdk.ModifierType.Button1Mask, new TargetEntry [] { DragDropTarget.UriList }, Gdk.DragAction.Copy | Gdk.DragAction.Move);
-            box.DragDataGet += (o, a) => {
-                var uri = GetCoverArtPath (get_track ());
-                if (uri != null) {
-                    a.SelectionData.Set (Gdk.Atom.Intern (DragDropTarget.UriList.Target, false), 8, System.Text.Encoding.UTF8.GetBytes (uri));
-                    a.RetVal = true;
-                }
+            return new EditorBox (widget) {
+                IsSensitive = is_sensitive,
+                GetTrack = get_track,
+                OnUpdated = on_updated
             };
-
-            return box;
         }
 
-        private static string GetCoverArtPath (TrackInfo track)
+        private class EditorBox : EventBox
         {
-            if (track != null) {
-                var uri = new SafeUri (CoverArtSpec.GetPath (track.ArtworkId));
-                if (Banshee.IO.File.Exists (uri)) {
-                    return uri.AbsoluteUri;
+            public Func<int, int, bool> IsSensitive;
+            public Func<TrackInfo> GetTrack;
+            public System.Action OnUpdated;
+
+            public EditorBox (Widget child)
+            {
+                Child = child;
+
+                ButtonPressEvent += (o, a) => {
+                    if (a.Event.Button == 3 && IsSensitive ((int)a.Event.X, (int)a.Event.Y)) {
+                        var menu = new Menu ();
+
+                        var choose = new MenuItem (Catalog.GetString ("Choose New Cover Art..."));
+                        choose.Activated += delegate {
+                            var track = GetTrack ();
+                            if (track != null) {
+                                var dialog = new Banshee.Gui.Dialogs.ImageFileChooserDialog ();
+                                var resp = dialog.Run ();
+                                string filename = dialog.Filename;
+                                dialog.Destroy ();
+                                if (resp == (int)Gtk.ResponseType.Ok) {
+                                    SetCoverArt (track, filename);
+                                }
+                            }
+                        };
+
+                        var delete = new MenuItem (Catalog.GetString ("Delete This Cover Art"));
+                        delete.Activated += delegate {
+                            var track = GetTrack ();
+                            if (track != null) {
+                                DeleteCoverArt (track);
+                                NotifyUpdated (track);
+                            }
+                        };
+
+                        var uri = GetCoverArtPath (GetTrack ());
+                        choose.Sensitive = uri != null;
+                        if (uri == null || !Banshee.IO.File.Exists (uri)) {
+                            delete.Sensitive = false;
+                        }
+
+                        menu.Append (choose);
+                        menu.Append (delete);
+                        menu.ShowAll ();
+                        menu.Popup ();
+                    }
+                };
+
+                Gtk.Drag.SourceSet (this, Gdk.ModifierType.Button1Mask, new TargetEntry [] { DragDropTarget.UriList }, Gdk.DragAction.Copy | Gdk.DragAction.Move);
+                DragDataGet += (o, a) => {
+                    var uri = GetCoverArtPath (GetTrack ());
+                    if (uri != null) {
+                        if (Banshee.IO.File.Exists (uri)) {
+                            a.SelectionData.Set (
+                                Gdk.Atom.Intern (DragDropTarget.UriList.Target, false), 8,
+                                Encoding.UTF8.GetBytes (uri.AbsoluteUri)
+                            );
+                        }
+                    }
+                };
+
+                Gtk.Drag.DestSet (this, Gtk.DestDefaults.All, new TargetEntry [] { DragDropTarget.UriList }, Gdk.DragAction.Copy);
+                DragDataReceived += (o, a) => {
+                    SetCoverArt (GetTrack (), Encoding.UTF8.GetString (a.SelectionData.Data));
+                };
+            }
+
+            private void SetCoverArt (TrackInfo track, string path)
+            {
+                if (track == null)
+                    return;
+
+                var from_uri = new SafeUri (new System.Uri (path));
+
+                var to_uri = new SafeUri (CoverArtSpec.GetPathForNewFile (track.ArtworkId, from_uri.AbsoluteUri));
+                if (to_uri != null) {
+                    // Make sure the incoming file exists
+                    if (!Banshee.IO.File.Exists (from_uri)) {
+                        Hyena.Log.WarningFormat ("New cover art file not found: {0}", path);
+                        return;
+                    }
+
+                    DeleteCoverArt (track);
+                    Banshee.IO.File.Copy (from_uri, to_uri, true);
+                    NotifyUpdated (track);
+
+                    Hyena.Log.DebugFormat ("Got new cover art file for {0}: {1}", track.DisplayAlbumTitle, path);
                 }
             }
 
-            return null;
+            private void NotifyUpdated (TrackInfo track)
+            {
+                var cur = ServiceManager.PlayerEngine.CurrentTrack;
+                if (cur != null && cur.TrackEqual (track)) {
+                    ServiceManager.PlayerEngine.TrackInfoUpdated ();
+                }
+
+                OnUpdated ();
+            }
+
+            private void DeleteCoverArt (TrackInfo track)
+            {
+                if (track != null) {
+                    var uri = new SafeUri (CoverArtSpec.GetPath (track.ArtworkId));
+                    if (Banshee.IO.File.Exists (uri)) {
+                        Banshee.IO.File.Delete (uri);
+                    }
+                    ServiceManager.Get<ArtworkManager> ().ClearCacheFor (track.ArtworkId);
+                }
+            }
+
+            private SafeUri GetCoverArtPath (TrackInfo track)
+            {
+                if (track != null) {
+                    return new SafeUri (CoverArtSpec.GetPath (track.ArtworkId));
+                }
+
+                return null;
+            }
         }
     }
 }
diff --git a/src/Core/Banshee.ThickClient/Banshee.Gui.TrackEditor/TrackEditorDialog.cs b/src/Core/Banshee.ThickClient/Banshee.Gui.TrackEditor/TrackEditorDialog.cs
index d4b6987..2f6a9ec 100644
--- a/src/Core/Banshee.ThickClient/Banshee.Gui.TrackEditor/TrackEditorDialog.cs
+++ b/src/Core/Banshee.ThickClient/Banshee.Gui.TrackEditor/TrackEditorDialog.cs
@@ -36,6 +36,7 @@ using Gtk;
 using Hyena.Gui;
 using Hyena.Widgets;
 
+using Banshee.Base;
 using Banshee.Kernel;
 using Banshee.Sources;
 using Banshee.ServiceStack;
@@ -158,7 +159,7 @@ namespace Banshee.Gui.TrackEditor
                 CoverArtEditor.For (header_image,
                     (x, y) => true,
                     () => CurrentTrack,
-                    () => { LoadCoverArt (CurrentTrack); }
+                    () => LoadCoverArt (CurrentTrack)
                 )
             );
 
@@ -419,9 +420,12 @@ namespace Banshee.Gui.TrackEditor
             if (current_track == null)
                 return;
 
-            ArtworkManager artwork = ServiceManager.Get<ArtworkManager> ();
-            Gdk.Pixbuf cover_art = artwork.LookupScalePixbuf (current_track.ArtworkId, 64);
+            var artwork = ServiceManager.Get<ArtworkManager> ();
+            var cover_art = artwork.LookupScalePixbuf (current_track.ArtworkId, 64);
+
+            header_image.Clear ();
             header_image.Pixbuf = cover_art;
+
             if (cover_art == null) {
                 header_image.IconName = "media-optical";
                 header_image.PixelSize = 64;
@@ -429,6 +433,8 @@ namespace Banshee.Gui.TrackEditor
             } else {
                 header_image_frame.ShadowType = ShadowType.In;
             }
+
+            header_image.QueueDraw ();
         }
 
         public void ForeachNonCurrentTrack (EditorTrackOperationClosure closure)
diff --git a/src/Core/Banshee.ThickClient/Banshee.Gui.Widgets/TrackInfoDisplay.cs b/src/Core/Banshee.ThickClient/Banshee.Gui.Widgets/TrackInfoDisplay.cs
index 19f5f48..004098a 100644
--- a/src/Core/Banshee.ThickClient/Banshee.Gui.Widgets/TrackInfoDisplay.cs
+++ b/src/Core/Banshee.ThickClient/Banshee.Gui.Widgets/TrackInfoDisplay.cs
@@ -135,7 +135,7 @@ namespace Banshee.Gui.Widgets
             return CoverArtEditor.For (display,
                 (x, y) => display.IsWithinCoverart (x, y),
                 () => display.CurrentTrack,
-                () => display.LoadImage (display.CurrentTrack, false, true)
+                () => {}
             );
         }
 
@@ -191,7 +191,7 @@ namespace Banshee.Gui.Widgets
             if (current_track == null) {
                 LoadCurrentTrack ();
             } else {
-                LoadImage (current_track, false, true);
+                LoadImage (current_track, true);
             }
         }
 
@@ -399,17 +399,17 @@ namespace Banshee.Gui.Widgets
 
             incoming_track = track;
 
-            LoadImage (track, force_reload, false);
+            LoadImage (track, force_reload);
 
             if (stage.Actor == null) {
                 stage.Reset ();
             }
         }
 
-        private void LoadImage (TrackInfo track, bool track_updated, bool force)
+        private void LoadImage (TrackInfo track, bool force)
         {
             string artwork_id = track.ArtworkId;
-            if (current_artwork_id != artwork_id || force || (track_updated && IsMissingImage (current_image))) {
+            if (current_artwork_id != artwork_id || force) {
                 current_artwork_id = artwork_id;
                 incoming_image = artwork_manager.LookupScaleSurface (artwork_id, ArtworkSizeRequest);
             }



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