[banshee] RescanPipeline: receive a Func<> to warn about high removal (bgo#577225)



commit be00cb6234e5d5881c7414ac1a3a505321b9d2b1
Author: Olivier Dufour <olivier duff gmail com>
Date:   Sat Jan 12 19:00:10 2013 +0000

    RescanPipeline: receive a Func<> to warn about high removal (bgo#577225)
    
    Even though the current Rescan operation for the music library doesn't
    remove (for now) non-existent tracks that are not inside the default folder
    of its source (normally $HOME/Music ), there could be a possibility that
    a user set up some symlinks inside this folder that linked to a removable
    drive, or that the mount point was inside this subtree.
    
    In those cases, whenever a Rescan operation was done (either by the menu
    or triggered by the LibraryWatcher extension), all tracks would be removed
    from the library, which would be especially bad if there was data that the
    user couldn't recover (for example if the user kept its ratings outside the
    files), because we don't have yet any automatic DB-backup mechanism.
    
    This change fixes this scenario by prompting the user a confirmation dialog
    that would pop up if the amount of tracks to be removed would be greater
    than 50.
    
    Signed-off-by: Andres G. Aragoneses <knocte gmail com>

 build/build.environment.mk                         |    2 +-
 .../Banshee.Collection/RescanPipeline.cs           |   47 +++++++++++++++-----
 .../Banshee.Gui/GlobalActions.cs                   |   13 +++++-
 .../Banshee.Gui/TrackActions.cs                    |   27 +++++++++++
 src/Dap/Banshee.Dap/Banshee.Dap.Gui/DapActions.cs  |   32 -------------
 src/Dap/Banshee.Dap/Banshee.Dap/DapSync.cs         |   13 +++++-
 .../LibraryWatcherService.cs                       |   29 +++++++++++-
 7 files changed, 113 insertions(+), 50 deletions(-)
---
diff --git a/build/build.environment.mk b/build/build.environment.mk
index 508e261..a524914 100644
--- a/build/build.environment.mk
+++ b/build/build.environment.mk
@@ -136,7 +136,7 @@ REF_EXTENSION_EMUSIC_STORE = $(LINK_BANSHEE_WEBBROWSER_DEPS) $(LINK_EXTENSION_EM
 REF_EXTENSION_FILESYSTEMQUEUE = $(LINK_BANSHEE_THICKCLIENT_DEPS)
 REF_EXTENSION_INTERNETRADIO = $(LINK_BANSHEE_THICKCLIENT_DEPS)
 REF_EXTENSION_INTERNETARCHIVE = $(LINK_BANSHEE_THICKCLIENT_DEPS)
-REF_EXTENSION_LIBRARYWATCHER = $(LINK_BANSHEE_SERVICES_DEPS)
+REF_EXTENSION_LIBRARYWATCHER = $(LINK_BANSHEE_THICKCLIENT_DEPS)
 REF_EXTENSION_MINIMODE = $(LINK_BANSHEE_THICKCLIENT_DEPS)
 REF_EXTENSION_MEEGO = $(LINK_BANSHEE_THICKCLIENT_DEPS)
 LINK_EXTENSION_MEEGO = -r:$(DIR_BIN)/Banshee.MeeGo.dll $(REF_EXTENSION_MEEGO)
diff --git a/src/Core/Banshee.Services/Banshee.Collection/RescanPipeline.cs b/src/Core/Banshee.Services/Banshee.Collection/RescanPipeline.cs
index 8da1020..9faaaba 100644
--- a/src/Core/Banshee.Services/Banshee.Collection/RescanPipeline.cs
+++ b/src/Core/Banshee.Services/Banshee.Collection/RescanPipeline.cs
@@ -60,11 +60,14 @@ namespace Banshee.Collection
         private PrimarySource psource;
         private BatchUserJob job;
         private TrackSyncPipelineElement track_sync;
+        private Func<int, bool> remove_confirmation;
+        private readonly int MAX_NOWARN_TRACKS_REMOVAL = 50;
 
-        public RescanPipeline (LibrarySource psource) : base ()
+        public RescanPipeline (LibrarySource psource, Func<int, bool> removeConfirmation) : base ()
         {
             this.psource = psource;
             scan_started = DateTime.Now;
+            remove_confirmation = removeConfirmation;
 
             AddElement (new Banshee.IO.DirectoryScannerPipelineElement ());
             AddElement (track_sync = new TrackSyncPipelineElement (psource, scan_started));
@@ -94,7 +97,7 @@ namespace Banshee.Collection
         {
             job.Finish ();
 
-            if (cancelled) {
+            if (cancelled || remove_confirmation == null) {
                 return;
             }
 
@@ -107,20 +110,40 @@ namespace Banshee.Collection
             );
             string uri = Hyena.StringUtil.EscapeLike (new SafeUri (psource.BaseDirectoryWithSeparator).AbsoluteUri) + "%";
 
-            ServiceManager.DbConnection.Execute (String.Format (@"BEGIN;
-                    DELETE FROM CorePlaylistEntries WHERE TrackID IN (SELECT TrackID FROM CoreTracks {0});
-                    DELETE FROM CoreSmartPlaylistEntries WHERE TrackID IN (SELECT TrackID FROM CoreTracks {0});
-                    DELETE FROM CoreTracks {0}; COMMIT",
-                condition),
-                psource.DbId, uri, scan_started,
-                psource.DbId, uri, scan_started,
-                psource.DbId, uri, scan_started
-            );
+            int remove_count = ServiceManager.DbConnection.Query<int> (
+                String.Format (@"SELECT COUNT('x') FROM CoreTracks {0}", condition),
+                psource.DbId, uri, scan_started);
+
+            if (remove_count > MAX_NOWARN_TRACKS_REMOVAL) {
+
+                if (!remove_confirmation (remove_count)) {
+                    Refresh ();
+                    return;
+                }
+            }
+
+            if (remove_count > 0) {
+
+                ServiceManager.DbConnection.Execute (String.Format (@"BEGIN;
+                        DELETE FROM CorePlaylistEntries WHERE TrackID IN (SELECT TrackID FROM CoreTracks {0});
+                        DELETE FROM CoreSmartPlaylistEntries WHERE TrackID IN (SELECT TrackID FROM CoreTracks {0});
+                        DELETE FROM CoreTracks {0}; COMMIT",
+                    condition),
+                    psource.DbId, uri, scan_started,
+                    psource.DbId, uri, scan_started,
+                    psource.DbId, uri, scan_started
+                );
+            }
 
             // TODO prune artists/albums
+            Refresh ();
+            //Hyena.Log.DebugFormat ("Have {0} items after delete", ServiceManager.DbConnection.Query<int>("select count(*) from coretracks where primarysourceid=?", psource.DbId));
+        }
+
+        private void Refresh ()
+        {
             psource.Reload ();
             psource.NotifyTracksChanged ();
-            //Hyena.Log.DebugFormat ("Have {0} items after delete", ServiceManager.DbConnection.Query<int>("select count(*) from coretracks where primarysourceid=?", psource.DbId));
         }
     }
 
diff --git a/src/Core/Banshee.ThickClient/Banshee.Gui/GlobalActions.cs b/src/Core/Banshee.ThickClient/Banshee.Gui/GlobalActions.cs
index 373da2e..d196637 100644
--- a/src/Core/Banshee.ThickClient/Banshee.Gui/GlobalActions.cs
+++ b/src/Core/Banshee.ThickClient/Banshee.Gui/GlobalActions.cs
@@ -80,7 +80,18 @@ namespace Banshee.Gui
                 new ActionEntry ("RescanAction", null,
                                  Catalog.GetString ("Rescan Music Library"), null,
                                  Catalog.GetString ("Rescan the Music Library folder"), delegate {
-                    new Banshee.Collection.RescanPipeline (ServiceManager.SourceManager.MusicLibrary);
+                    new Banshee.Collection.RescanPipeline (ServiceManager.SourceManager.MusicLibrary, tracks => {
+
+                        string msg = String.Format (
+                            Catalog.GetPluralString (
+                            // singular form unused b/c we know it's > 1, but we still need GetPlural
+                            "The rescan operation will remove one track from your music library.",
+                            "The rescan operation will remove {0} tracks from your music library.",
+                            tracks),
+                            tracks);
+
+                        return TrackActions.ConfirmRemove (msg);
+                    });
                 }),
 
                 // Help Menu
diff --git a/src/Core/Banshee.ThickClient/Banshee.Gui/TrackActions.cs b/src/Core/Banshee.ThickClient/Banshee.Gui/TrackActions.cs
index bd4b97e..609a5d1 100644
--- a/src/Core/Banshee.ThickClient/Banshee.Gui/TrackActions.cs
+++ b/src/Core/Banshee.ThickClient/Banshee.Gui/TrackActions.cs
@@ -639,5 +639,32 @@ namespace Banshee.Gui
             }
             return ret;
         }
+
+        public static bool ConfirmRemove (string header)
+        {
+            string message = Catalog.GetString ("Are you sure you want to continue?");
+
+            bool remove_tracks = false;
+            ThreadAssist.BlockingProxyToMain (() => {
+
+                var md = new HigMessageDialog (
+                    ServiceManager.Get<GtkElementsService> ().PrimaryWindow,
+                    DialogFlags.DestroyWithParent, MessageType.Warning,
+                    ButtonsType.None, header, message
+                );
+                md.AddButton ("gtk-cancel", ResponseType.No, true);
+                md.AddButton (Catalog.GetString ("Remove tracks"), ResponseType.Yes, false);
+
+                try {
+                    if (md.Run () == (int) ResponseType.Yes) {
+                        remove_tracks = true;
+                    }
+                } finally {
+                    md.Destroy ();
+                }
+            });
+            return remove_tracks;
+        }
+
     }
 }
diff --git a/src/Dap/Banshee.Dap/Banshee.Dap.Gui/DapActions.cs b/src/Dap/Banshee.Dap/Banshee.Dap.Gui/DapActions.cs
index facf99f..949007c 100644
--- a/src/Dap/Banshee.Dap/Banshee.Dap.Gui/DapActions.cs
+++ b/src/Dap/Banshee.Dap/Banshee.Dap.Gui/DapActions.cs
@@ -98,37 +98,5 @@ namespace Banshee.Dap.Gui
             }
         }
 
-        internal static bool ConfirmUserAction (int tracks_to_remove)
-        {
-            string header = String.Format (
-                Catalog.GetPluralString (
-                    // singular form unused b/c we know it's > 1, but we still need GetPlural
-                    "The sync operation will remove one track from your device.",
-                    "The sync operation will remove {0} tracks from your device.",
-                    tracks_to_remove),
-                tracks_to_remove);
-            string message = Catalog.GetString ("Are you sure you want to continue?");
-
-            bool remove_tracks = false;
-            ThreadAssist.BlockingProxyToMain (() => {
-
-                var md = new HigMessageDialog (
-                    ServiceManager.Get<GtkElementsService> ().PrimaryWindow,
-                    DialogFlags.DestroyWithParent, MessageType.Warning,
-                    ButtonsType.None, header, message
-                );
-                md.AddButton ("gtk-cancel", ResponseType.No, true);
-                md.AddButton (Catalog.GetString ("Remove tracks"), ResponseType.Yes, false);
-
-                try {
-                    if (md.Run () == (int) ResponseType.Yes) {
-                        remove_tracks = true;
-                    }
-                } finally {
-                    md.Destroy ();
-                }
-            });
-            return remove_tracks;
-        }
     }
 }
diff --git a/src/Dap/Banshee.Dap/Banshee.Dap/DapSync.cs b/src/Dap/Banshee.Dap/Banshee.Dap/DapSync.cs
index ceeb233..38f5a43 100644
--- a/src/Dap/Banshee.Dap/Banshee.Dap/DapSync.cs
+++ b/src/Dap/Banshee.Dap/Banshee.Dap/DapSync.cs
@@ -45,7 +45,7 @@ using Banshee.SmartPlaylist;
 using Banshee.Query;
 using Banshee.Preferences;
 
-using Banshee.Dap.Gui;
+using Banshee.Gui;
 
 namespace Banshee.Dap
 {
@@ -357,7 +357,16 @@ namespace Banshee.Dap
                     library_sync.Sync ();
                 } catch (DapLibrarySync.PossibleUserErrorException e) {
 
-                    if (DapActions.ConfirmUserAction (e.TracksToRemove)) {
+                    var tracks_to_remove = e.TracksToRemove;
+                    string msg = String.Format (
+                        Catalog.GetPluralString (
+                        // singular form unused b/c we know it's > 1, but we still need GetPlural
+                        "The sync operation will remove one track from your device.",
+                        "The sync operation will remove {0} tracks from your device.",
+                        tracks_to_remove),
+                        tracks_to_remove);
+
+                    if (TrackActions.ConfirmRemove (msg)) {
                         library_sync.Sync (true);
                     }
 
diff --git a/src/Extensions/Banshee.LibraryWatcher/Banshee.LibraryWatcher/LibraryWatcherService.cs b/src/Extensions/Banshee.LibraryWatcher/Banshee.LibraryWatcher/LibraryWatcherService.cs
index 6e7558e..c474564 100644
--- a/src/Extensions/Banshee.LibraryWatcher/Banshee.LibraryWatcher/LibraryWatcherService.cs
+++ b/src/Extensions/Banshee.LibraryWatcher/Banshee.LibraryWatcher/LibraryWatcherService.cs
@@ -36,6 +36,9 @@ using Banshee.Sources;
 using Banshee.ServiceStack;
 using Banshee.Library;
 
+using Banshee.Gui;
+using Banshee.I18n;
+
 namespace Banshee.LibraryWatcher
 {
     public class LibraryWatcherService : IExtensionService, IDisposable, IDelayedInitializeService
@@ -68,11 +71,33 @@ namespace Banshee.LibraryWatcher
             AddLibrary (ServiceManager.SourceManager.VideoLibrary);
 
             if (ServiceManager.SourceManager.MusicLibrary.Count == 0) {
-                new Banshee.Collection.RescanPipeline (ServiceManager.SourceManager.MusicLibrary);
+                new Banshee.Collection.RescanPipeline (ServiceManager.SourceManager.MusicLibrary, tracks => {
+
+                    string msg = String.Format (
+                        Catalog.GetPluralString (
+                        // singular form unused b/c we know it's > 1, but we still need GetPlural
+                        "Library Watcher extension just detected an action that would trigger the removal of one track from your music library.",
+                        "Library Watcher extension just detected an action that would trigger the removal of {0} tracks from your music library.",
+                        tracks),
+                        tracks);
+
+                    return TrackActions.ConfirmRemove (msg);
+                });
             }
 
             if (ServiceManager.SourceManager.VideoLibrary.Count == 0) {
-                new Banshee.Collection.RescanPipeline (ServiceManager.SourceManager.VideoLibrary);
+                new Banshee.Collection.RescanPipeline (ServiceManager.SourceManager.VideoLibrary, tracks => {
+
+                    string msg = String.Format (
+                        Catalog.GetPluralString (
+                        // singular form unused b/c we know it's > 1, but we still need GetPlural
+                        "Library Watcher extension just detected an action that would trigger the removal of one track from your video library.",
+                        "Library Watcher extension just detected an action that would trigger the removal of {0} tracks from your video library.",
+                        tracks),
+                        tracks);
+
+                    return TrackActions.ConfirmRemove (msg);
+                });
             }
         }
 



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