banshee r3077 - in trunk/banshee: . src/Core/Banshee.Services src/Core/Banshee.Services/Banshee.Collection.Database src/Core/Banshee.Services/Banshee.Database src/Core/Banshee.Services/Banshee.Sources src/Core/Banshee.ThickClient/Banshee.Gui.Widgets src/Core/Hyena/Hyena.Data src/Core/Hyena/Hyena.Data.Query src/Core/Hyena/Hyena.Data.Sqlite src/Core/Nereid/Nereid



Author: gburt
Date: Tue Jan 29 03:32:02 2008
New Revision: 3077
URL: http://svn.gnome.org/viewvc/banshee?rev=3077&view=rev

Log:
2008-01-28  Gabriel Burt  <gabriel burt gmail com>

	* src/Core/Banshee.Services/Banshee.Collection.Database/AlbumListDatabaseModel.cs:
	* src/Core/Banshee.Services/Banshee.Collection.Database/ArtistListDatabaseModel.cs:
	Implement SelectAggregates.

	* src/Core/Banshee.Services/Banshee.Collection.Database/TrackListDatabaseModel.cs:
	Add Duration and FileSize properties.

	* src/Core/Banshee.Services/Makefile.am:
	* src/Core/Banshee.Services/Banshee.Sources/IDurationAggregator.cs:
	* src/Core/Banshee.Services/Banshee.Sources/IFileSizeAggregator.cs: New
	interfaces for determining if a source has certain properties.

	* src/Core/Banshee.Services/Banshee.Sources/DatabaseSource.cs: Implement
	both new interfaces.

	* src/Core/Banshee.Services/Banshee.Sources/Source.cs: New GetStatusText
	method that the interface with default implementation that returns count,
	duration, and file size.

	* src/Core/Banshee.ThickClient/Banshee.Gui.Widgets/UserJobTileHost.cs:
	Place VBox inside of Alignment so we can get our top padding, but only
	show it when we are shown (instead of spacing in our parent vbox that is
	always there).

	* src/Core/Hyena/Hyena.Data.Query/FileSizeQueryValue.cs: Add new ctor.

	* src/Core/Hyena/Hyena.Data.Sqlite/HyenaSqliteCommand.cs: Rename variable
	for clarity.

	* src/Core/Hyena/Hyena.Data.Sqlite/ICacheableDatabaseModel.cs: Add
	SelectAggregates property, used by models to load aggregate values (eg
	SUM(FileSize) when the count is taken.

	* src/Core/Hyena/Hyena.Data.Sqlite/SqliteModelCache.cs: Add support for
	SelectAggregate properties.  Add AggregatesUpdated event so models can
	handle the results of the query themselves (except the count, which we
	still handle).

	* src/Core/Banshee.Services/Banshee.Database/BansheeModelProvider.cs:
	* src/Core/Hyena/Hyena.Data.Sqlite/SqliteModelProvider.cs: Make TableName
	public.

	* src/Core/Hyena/Hyena.Data/IFilterable.cs: Revert previous
	UnfilteredCount -> FilteredCount change.

	* src/Core/Nereid/Nereid/PlayerInterface.cs: Add BuildFooter method, add
	the status label in the footer, keep it updated as the source track model
	changes.


Added:
   trunk/banshee/src/Core/Banshee.Services/Banshee.Sources/IDurationAggregator.cs
   trunk/banshee/src/Core/Banshee.Services/Banshee.Sources/IFileSizeAggregator.cs
Modified:
   trunk/banshee/ChangeLog
   trunk/banshee/src/Core/Banshee.Services/Banshee.Collection.Database/AlbumListDatabaseModel.cs
   trunk/banshee/src/Core/Banshee.Services/Banshee.Collection.Database/ArtistListDatabaseModel.cs
   trunk/banshee/src/Core/Banshee.Services/Banshee.Collection.Database/TrackListDatabaseModel.cs
   trunk/banshee/src/Core/Banshee.Services/Banshee.Database/BansheeModelProvider.cs
   trunk/banshee/src/Core/Banshee.Services/Banshee.Sources/DatabaseSource.cs
   trunk/banshee/src/Core/Banshee.Services/Banshee.Sources/Source.cs
   trunk/banshee/src/Core/Banshee.Services/Makefile.am
   trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Gui.Widgets/UserJobTileHost.cs
   trunk/banshee/src/Core/Hyena/Hyena.Data.Query/FileSizeQueryValue.cs
   trunk/banshee/src/Core/Hyena/Hyena.Data.Sqlite/HyenaSqliteCommand.cs
   trunk/banshee/src/Core/Hyena/Hyena.Data.Sqlite/ICacheableDatabaseModel.cs
   trunk/banshee/src/Core/Hyena/Hyena.Data.Sqlite/SqliteModelCache.cs
   trunk/banshee/src/Core/Hyena/Hyena.Data.Sqlite/SqliteModelProvider.cs
   trunk/banshee/src/Core/Hyena/Hyena.Data/IFilterable.cs
   trunk/banshee/src/Core/Nereid/Nereid/PlayerInterface.cs

Modified: trunk/banshee/src/Core/Banshee.Services/Banshee.Collection.Database/AlbumListDatabaseModel.cs
==============================================================================
--- trunk/banshee/src/Core/Banshee.Services/Banshee.Collection.Database/AlbumListDatabaseModel.cs	(original)
+++ trunk/banshee/src/Core/Banshee.Services/Banshee.Collection.Database/AlbumListDatabaseModel.cs	Tue Jan 29 03:32:02 2008
@@ -135,6 +135,8 @@
             get { return 20; }
         }
 
+        public string SelectAggregates { get { return null; } }
+
         //private const string primary_key = "CoreAlbums.AlbumID";
 
         public string ReloadFragment {

Modified: trunk/banshee/src/Core/Banshee.Services/Banshee.Collection.Database/ArtistListDatabaseModel.cs
==============================================================================
--- trunk/banshee/src/Core/Banshee.Services/Banshee.Collection.Database/ArtistListDatabaseModel.cs	(original)
+++ trunk/banshee/src/Core/Banshee.Services/Banshee.Collection.Database/ArtistListDatabaseModel.cs	Tue Jan 29 03:32:02 2008
@@ -104,6 +104,8 @@
         public int FetchCount {
             get { return 20; }
         }
+
+        public string SelectAggregates { get { return null; } }
         
         public string ReloadFragment {
             get { return reload_fragment; }

Modified: trunk/banshee/src/Core/Banshee.Services/Banshee.Collection.Database/TrackListDatabaseModel.cs
==============================================================================
--- trunk/banshee/src/Core/Banshee.Services/Banshee.Collection.Database/TrackListDatabaseModel.cs	(original)
+++ trunk/banshee/src/Core/Banshee.Services/Banshee.Collection.Database/TrackListDatabaseModel.cs	Tue Jan 29 03:32:02 2008
@@ -33,6 +33,7 @@
 using System.Collections.Generic;
 
 using Mono.Unix;
+using Hyena;
 using Hyena.Data;
 using Hyena.Data.Sqlite;
 using Hyena.Data.Query;
@@ -48,8 +49,13 @@
         private BansheeDbConnection connection;
         private BansheeModelProvider<LibraryTrackInfo> provider;
         private BansheeModelCache<LibraryTrackInfo> cache;
-        private int filtered_count;
         private int count;
+        private TimeSpan duration;
+        private long filesize;
+
+        private int filtered_count;
+        private TimeSpan filtered_duration;
+        private long filtered_filesize;
         
         private ISortableColumn sort_column;
         private string sort_query;
@@ -65,12 +71,12 @@
         
         private int rows_in_view;
         
-        
         public TrackListDatabaseModel (BansheeDbConnection connection, string uuid)
         {
             this.connection = connection;
             provider = LibraryTrackInfo.Provider;
             cache = new BansheeModelCache <LibraryTrackInfo> (connection, uuid, this, provider);
+            cache.AggregatesUpdated += HandleCacheAggregatesUpdated;
             Refilter ();
         }
         
@@ -203,6 +209,12 @@
                 cache.Clear ();
             }
         }
+
+        private void HandleCacheAggregatesUpdated (IDataReader reader)
+        {
+            filtered_duration = TimeSpan.FromMilliseconds (reader.IsDBNull (1) ? 0 : Convert.ToInt64 (reader[1]));
+            filtered_filesize = reader.IsDBNull (2) ? 0 : Convert.ToInt64 (reader[2]);
+        }
         
         public override void Clear()
         {
@@ -220,9 +232,13 @@
                 provider.From, JoinFragment, provider.Where, ConditionFragment
             );
 
-            count = connection.QueryInt32 (String.Format (
-                "SELECT COUNT(*) {0}", unfiltered_query
-            ));
+            using (IDataReader reader = connection.ExecuteReader (String.Format (
+                "SELECT COUNT(*), {0} {1}", SelectAggregates, unfiltered_query)))
+            {
+                count = Convert.ToInt32 (reader[0]);
+                duration = TimeSpan.FromMilliseconds (reader.IsDBNull (1) ? 0 : Convert.ToInt64 (reader[1]));
+                filesize = reader.IsDBNull (2) ? 0 : Convert.ToInt64 (reader[2]);
+            }
 
             StringBuilder qb = new StringBuilder ();
                 
@@ -271,11 +287,27 @@
         }
 
         public override int Count {
-            get { return count; }
+            get { return filtered_count; }
+        }
+
+        public TimeSpan Duration {
+            get { return duration; }
+        }
+
+        public long FileSize {
+            get { return filesize; }
         }
         
-        public int FilteredCount {
-            get { return filtered_count; }
+        public int UnfilteredCount {
+            get { return count; }
+        }
+
+        public TimeSpan FilteredDuration {
+            get { return filtered_duration; }
+        }
+
+        public long FilteredFileSize {
+            get { return filtered_filesize; }
         }
         
         public string Filter {
@@ -393,6 +425,10 @@
             get { return RowsInView > 0 ? RowsInView * 5 : 100; }
         }
 
+        public string SelectAggregates {
+            get { return "SUM(CoreTracks.Duration), SUM(CoreTracks.FileSize)"; }
+        }
+
         // Implement IDatabaseModel
         public string ReloadFragment {
             get { return reload_fragment; }

Modified: trunk/banshee/src/Core/Banshee.Services/Banshee.Database/BansheeModelProvider.cs
==============================================================================
--- trunk/banshee/src/Core/Banshee.Services/Banshee.Database/BansheeModelProvider.cs	(original)
+++ trunk/banshee/src/Core/Banshee.Services/Banshee.Database/BansheeModelProvider.cs	Tue Jan 29 03:32:02 2008
@@ -47,7 +47,7 @@
             Init ();
         }
         
-        protected override sealed string TableName {
+        public override sealed string TableName {
             get { return table_name; }
         }
         

Modified: trunk/banshee/src/Core/Banshee.Services/Banshee.Sources/DatabaseSource.cs
==============================================================================
--- trunk/banshee/src/Core/Banshee.Services/Banshee.Sources/DatabaseSource.cs	(original)
+++ trunk/banshee/src/Core/Banshee.Services/Banshee.Sources/DatabaseSource.cs	Tue Jan 29 03:32:02 2008
@@ -42,7 +42,7 @@
 
 namespace Banshee.Sources
 {
-    public abstract class DatabaseSource : Source, ITrackModelSource
+    public abstract class DatabaseSource : Source, ITrackModelSource, IDurationAggregator, IFileSizeAggregator
     {
         protected delegate void TrackRangeHandler (TrackListDatabaseModel model, RangeCollection.Range range);
 
@@ -67,6 +67,26 @@
             get { return track_model.Count; }
         }
 
+        public override int UnfilteredCount {
+            get { return track_model.UnfilteredCount; }
+        }
+
+        public TimeSpan Duration {
+            get { return track_model.Duration; }
+        }
+
+        public TimeSpan FilteredDuration {
+            get { return track_model.FilteredDuration; }
+        }
+
+        public long FileSize {
+            get { return track_model.FileSize; }
+        }
+
+        public long FilteredFileSize {
+            get { return track_model.FilteredFileSize; }
+        }
+
         public override string FilterQuery {
             set {
                 base.FilterQuery = value;

Added: trunk/banshee/src/Core/Banshee.Services/Banshee.Sources/IDurationAggregator.cs
==============================================================================
--- (empty file)
+++ trunk/banshee/src/Core/Banshee.Services/Banshee.Sources/IDurationAggregator.cs	Tue Jan 29 03:32:02 2008
@@ -0,0 +1,38 @@
+//
+// IDurationAggregator.cs
+//
+// Author:
+//   Gabriel Burt <gburt novell com>
+//
+// Copyright (C) 2008 Novell, Inc.
+//
+// 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 interface IDurationAggregator
+    {
+        TimeSpan Duration { get; }
+        TimeSpan FilteredDuration { get; }
+    }
+}

Added: trunk/banshee/src/Core/Banshee.Services/Banshee.Sources/IFileSizeAggregator.cs
==============================================================================
--- (empty file)
+++ trunk/banshee/src/Core/Banshee.Services/Banshee.Sources/IFileSizeAggregator.cs	Tue Jan 29 03:32:02 2008
@@ -0,0 +1,36 @@
+//
+// IFileSizeAggregator.cs
+//
+// Author:
+//   Gabriel Burt <gburt novell com>
+//
+// Copyright (C) 2008 Novell, Inc.
+//
+// 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.
+//
+
+namespace Banshee.Sources
+{
+    public interface IFileSizeAggregator
+    {
+        long FileSize { get; }
+        long FilteredFileSize { get; }
+    }
+}

Modified: trunk/banshee/src/Core/Banshee.Services/Banshee.Sources/Source.cs
==============================================================================
--- trunk/banshee/src/Core/Banshee.Services/Banshee.Sources/Source.cs	(original)
+++ trunk/banshee/src/Core/Banshee.Services/Banshee.Sources/Source.cs	Tue Jan 29 03:32:02 2008
@@ -27,12 +27,14 @@
 //
 
 using System;
+using System.Text;
 using System.Collections;
 using System.Collections.Generic;
 
 using Mono.Unix;
 
 using Hyena.Data;
+using Hyena.Data.Query;
 
 using Banshee.Collection;
 using Banshee.ServiceStack;
@@ -288,8 +290,44 @@
             get { return true; }
         }
         
-        public virtual int Count {
-            get { return 0; }
+        public abstract int Count { get; }
+        public virtual int UnfilteredCount { get { return Count; } }
+
+        public virtual string GetStatusText ()
+        {
+            StringBuilder builder = new StringBuilder ();
+
+            int count = Count;
+            builder.AppendFormat (Catalog.GetPluralString ("{0} Item", "{0} Items", count), count);
+            
+            if (this is IDurationAggregator) {
+                builder.Append (", ");
+
+                TimeSpan span = (this as IDurationAggregator).FilteredDuration; 
+                if (span.Days > 0) {
+                    builder.AppendFormat (Catalog.GetPluralString ("{0} day", "{0} days", span.Days), span.Days);
+                    builder.Append (", ");
+                }
+                
+                if (span.Hours > 0) {
+                    builder.AppendFormat (Catalog.GetPluralString ("{0} hour", "{0} hours", span.Hours), span.Hours);
+                    builder.Append (", ");
+                }
+                
+                builder.AppendFormat (Catalog.GetPluralString ("{0} minute", "{0} minutes", span.Minutes), span.Minutes);
+                builder.Append (", ");
+                builder.AppendFormat (Catalog.GetPluralString ("{0} second", "{0} seconds", span.Seconds), span.Seconds);
+            }
+
+            if (this is IFileSizeAggregator) {
+                long bytes = (this as IFileSizeAggregator).FileSize;
+                if (bytes > 0) {
+                    builder.Append (", ");
+                    builder.AppendFormat (new FileSizeQueryValue (bytes).ToUserQuery ());
+                }
+            }
+            
+            return builder.ToString ();
         }
         
         string IService.ServiceName {

Modified: trunk/banshee/src/Core/Banshee.Services/Makefile.am
==============================================================================
--- trunk/banshee/src/Core/Banshee.Services/Makefile.am	(original)
+++ trunk/banshee/src/Core/Banshee.Services/Makefile.am	Tue Jan 29 03:32:02 2008
@@ -100,6 +100,8 @@
 	Banshee.SmartPlaylist/SmartPlaylistSource.cs \
 	Banshee.Sources/DatabaseSource.cs \
 	Banshee.Sources/ErrorSource.cs \
+	Banshee.Sources/IDurationAggregator.cs \
+	Banshee.Sources/IFileSizeAggregator.cs \
 	Banshee.Sources/IImportable.cs \
 	Banshee.Sources/ISource.cs \
 	Banshee.Sources/ISourceManager.cs \

Modified: trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Gui.Widgets/UserJobTileHost.cs
==============================================================================
--- trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Gui.Widgets/UserJobTileHost.cs	(original)
+++ trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Gui.Widgets/UserJobTileHost.cs	Tue Jan 29 03:32:02 2008
@@ -35,19 +35,24 @@
 
 namespace Banshee.Gui.Widgets
 {
-    public class UserJobTileHost : VBox
+    public class UserJobTileHost : Alignment
     {
+        private VBox box;
         private Dictionary<IUserJob, UserJobTile> job_tiles = new Dictionary<IUserJob, UserJobTile> ();
         
-        public UserJobTileHost ()
+        public UserJobTileHost () : base (0.0f, 0.0f, 1.0f, 1.0f)
         {
+            TopPadding = 5;
+
+            box = new VBox ();
+            box.Spacing = 8;
+            box.Show ();
+
             if (ServiceManager.Contains ("UserJobManager")) {
                 UserJobManager job_manager = ServiceManager.Get<UserJobManager> ("UserJobManager");
                 job_manager.JobAdded += OnJobAdded;
                 job_manager.JobRemoved += OnJobRemoved;
             }
-            
-            Spacing = 8;
         }
         
         private void AddJob (IUserJob job)
@@ -59,7 +64,7 @@
             if ((job.DelayShow && job.Progress < 0.33) || !job.DelayShow) {
                 UserJobTile tile = new UserJobTile (job);
                 job_tiles.Add (job, tile);
-                PackStart (tile, false, false, 0);
+                box.PackStart (tile, false, false, 0);
                 tile.Show ();
                 Show ();
             }
@@ -85,7 +90,7 @@
             lock (this) {
                 if (job_tiles.ContainsKey (args.Job)) {
                     UserJobTile tile = job_tiles[args.Job];
-                    Remove (tile);
+                    box.Remove (tile);
                     
                     if (job_tiles.Count <= 0) {
                         Hide ();

Modified: trunk/banshee/src/Core/Hyena/Hyena.Data.Query/FileSizeQueryValue.cs
==============================================================================
--- trunk/banshee/src/Core/Hyena/Hyena.Data.Query/FileSizeQueryValue.cs	(original)
+++ trunk/banshee/src/Core/Hyena/Hyena.Data.Query/FileSizeQueryValue.cs	Tue Jan 29 03:32:02 2008
@@ -49,6 +49,17 @@
             get { return factor; }
         }
 
+        public FileSizeQueryValue ()
+        {
+        }
+
+        public FileSizeQueryValue (long bytes)
+        {
+            value = bytes;
+            IsEmpty = false;
+            DetermineFactor ();
+        }
+
         public override void ParseUserQuery (string input)
         {
             if (input.Length > 1 && (input[input.Length - 1] == 'b' || input[input.Length - 1] == 'B')) {
@@ -75,6 +86,11 @@
         public override void ParseXml (XmlElement node)
         {
             base.ParseUserQuery (node.InnerText);
+            DetermineFactor ();
+        }
+
+        protected void DetermineFactor ()
+        {
             if (!IsEmpty && value != 0) {
                 foreach (FileSizeFactor factor in Enum.GetValues (typeof(FileSizeFactor))) {
                     if (value >= (long) factor) {

Modified: trunk/banshee/src/Core/Hyena/Hyena.Data.Sqlite/HyenaSqliteCommand.cs
==============================================================================
--- trunk/banshee/src/Core/Hyena/Hyena.Data.Sqlite/HyenaSqliteCommand.cs	(original)
+++ trunk/banshee/src/Core/Hyena/Hyena.Data.Sqlite/HyenaSqliteCommand.cs	Tue Jan 29 03:32:02 2008
@@ -54,13 +54,13 @@
 
 #endregion
 
-        public HyenaSqliteCommand (string command)
+        public HyenaSqliteCommand (string command_str)
         {
-            this.command = new SqliteCommand (command);
+            this.command = new SqliteCommand (command_str);
 
             int num_params = 0;
-            for (int i = 0; i < command.Length; i++) {
-                if (command [i] == '?') {
+            for (int i = 0; i < command_str.Length; i++) {
+                if (command_str [i] == '?') {
                     num_params++;
                 }
             }
@@ -68,9 +68,9 @@
             CreateParameters (num_params);
         }
 
-        public HyenaSqliteCommand (string command, params object [] param_values)
+        public HyenaSqliteCommand (string command_str, params object [] param_values)
         {
-            this.command = new SqliteCommand (command);
+            this.command = new SqliteCommand (command_str);
             CreateParameters (param_values.Length);
             ApplyValues (param_values);
         }

Modified: trunk/banshee/src/Core/Hyena/Hyena.Data.Sqlite/ICacheableDatabaseModel.cs
==============================================================================
--- trunk/banshee/src/Core/Hyena/Hyena.Data.Sqlite/ICacheableDatabaseModel.cs	(original)
+++ trunk/banshee/src/Core/Hyena/Hyena.Data.Sqlite/ICacheableDatabaseModel.cs	Tue Jan 29 03:32:02 2008
@@ -35,5 +35,6 @@
     public interface ICacheableDatabaseModel : ICacheableModel
     {
         string ReloadFragment { get; }
+        string SelectAggregates { get; }
     }
 }

Modified: trunk/banshee/src/Core/Hyena/Hyena.Data.Sqlite/SqliteModelCache.cs
==============================================================================
--- trunk/banshee/src/Core/Hyena/Hyena.Data.Sqlite/SqliteModelCache.cs	(original)
+++ trunk/banshee/src/Core/Hyena/Hyena.Data.Sqlite/SqliteModelCache.cs	Tue Jan 29 03:32:02 2008
@@ -48,6 +48,9 @@
         private bool warm;
         private int first_order_id;
 
+        public delegate void AggregatesUpdatedEventHandler (IDataReader reader);
+        public event AggregatesUpdatedEventHandler AggregatesUpdated;
+
         public SqliteModelCache (HyenaSqliteConnection connection,
                            string uuid,
                            ICacheableDatabaseModel model,
@@ -60,11 +63,17 @@
             
             CheckCacheTable ();
 
-            count_command = new HyenaSqliteCommand (
-                String.Format (
+            if (model.SelectAggregates != null) {
+                count_command = new HyenaSqliteCommand (String.Format (@"
+                    SELECT COUNT(*), {0} FROM {1} WHERE {2}
+                        IN (SELECT ItemID FROM {3} WHERE ModelID = ?)",
+                    model.SelectAggregates, provider.TableName, provider.PrimaryKey, CacheTableName
+                ));
+            } else {
+                count_command = new HyenaSqliteCommand (String.Format (
                     "SELECT COUNT(*) FROM {0} WHERE ModelID = ?", CacheTableName
-                )
-            );
+                ));
+            }
 
             FindOrCreateCacheModelId (String.Format ("{0}-{1}", uuid, typeof(T).Name));
 
@@ -116,7 +125,7 @@
         public int Count {
             get { return rows; }
         }
-        
+
         public int CacheId {
             get { return uid; }
         }
@@ -152,7 +161,7 @@
                 connection.Execute (reload_sql + model.ReloadFragment);
             //}
             first_order_id = -1;
-            UpdateCount ();
+            UpdateAggregates ();
             return rows;
         }
 
@@ -171,11 +180,16 @@
             //}
         }
         
-        protected void UpdateCount ()
+        protected void UpdateAggregates ()
         {
-            //using (new Timer (String.Format ("Counting items for {0}", db_model))) {
-                rows = Convert.ToInt32 (connection.ExecuteScalar (count_command.ApplyValues (uid)));
-            //}
+            using (IDataReader reader = connection.ExecuteReader (count_command.ApplyValues (uid))) {
+                rows = Convert.ToInt32 (reader[0]);
+
+                AggregatesUpdatedEventHandler handler = AggregatesUpdated;
+                if (handler != null) {
+                    handler (reader);
+                }
+            }
         }
         
         private void FindOrCreateCacheModelId (string id)
@@ -195,7 +209,7 @@
                 //Console.WriteLine ("Found existing cache for {0}: {1}", id, uid);
                 warm = true;
                 Clear ();
-                UpdateCount ();
+                UpdateAggregates ();
             }
         }
 

Modified: trunk/banshee/src/Core/Hyena/Hyena.Data.Sqlite/SqliteModelProvider.cs
==============================================================================
--- trunk/banshee/src/Core/Hyena/Hyena.Data.Sqlite/SqliteModelProvider.cs	(original)
+++ trunk/banshee/src/Core/Hyena/Hyena.Data.Sqlite/SqliteModelProvider.cs	Tue Jan 29 03:32:02 2008
@@ -57,7 +57,7 @@
         
         private const string HYENA_DATABASE_NAME = "hyena_database_master";
 
-        protected abstract string TableName { get; }
+        public abstract string TableName { get; }
         protected abstract int ModelVersion { get; }
         protected abstract int DatabaseVersion { get; }
         protected abstract void MigrateTable (int old_version);

Modified: trunk/banshee/src/Core/Hyena/Hyena.Data/IFilterable.cs
==============================================================================
--- trunk/banshee/src/Core/Hyena/Hyena.Data/IFilterable.cs	(original)
+++ trunk/banshee/src/Core/Hyena/Hyena.Data/IFilterable.cs	Tue Jan 29 03:32:02 2008
@@ -32,6 +32,6 @@
     {
         void Refilter();
         string Filter { get; set; }
-        int FilteredCount { get; }
+        int UnfilteredCount { get; }
     }
 }

Modified: trunk/banshee/src/Core/Nereid/Nereid/PlayerInterface.cs
==============================================================================
--- trunk/banshee/src/Core/Nereid/Nereid/PlayerInterface.cs	(original)
+++ trunk/banshee/src/Core/Nereid/Nereid/PlayerInterface.cs	Tue Jan 29 03:32:02 2008
@@ -57,6 +57,7 @@
         private VBox primary_vbox;
         private Toolbar header_toolbar;
         private HPaned views_pane;
+        private HBox footer_box;
         private ViewContainer view_container;
         
         // Major Interaction Components
@@ -64,6 +65,7 @@
         private CompositeTrackListView composite_view;
         private ScrolledWindow object_view_scroll;
         private ObjectListView object_view;
+        private Label status_label;
         
         // Cached service references
         private GtkElementsService elements_service;
@@ -122,6 +124,8 @@
            
             BuildHeader ();
             BuildViews ();
+            BuildFooter ();
+
             
             primary_vbox.Show ();
             Add (primary_vbox);
@@ -158,7 +162,6 @@
         private void BuildViews ()
         {
             VBox source_box = new VBox ();
-            source_box.Spacing = 5;
             
             views_pane = new HPaned ();
             view_container = new ViewContainer ();
@@ -190,6 +193,25 @@
             primary_vbox.PackStart (views_pane, true, true, 0);
         }
 
+        private void BuildFooter ()
+        {
+            footer_box = new HBox ();
+            footer_box.Spacing = 2;
+
+            status_label = new Label ();
+            //footer_box.PackStart (shuffle_toggle_button, false, false, 0);
+            //footer_box.PackStart (repeat_toggle_button, false, false, 0);
+            footer_box.PackStart (status_label, true, true, 0);
+            //footer_box.PackStart (song_properties_button, false, false, 0);
+
+            Alignment align = new Alignment (0.5f, 0.5f, 1.0f, 1.0f);
+            align.TopPadding = 5;
+            align.Add (footer_box);
+            align.ShowAll ();
+
+            primary_vbox.PackStart (align, false, true, 0);
+        }
+
 #endregion
 
 #region Configuration Loading/Saving        
@@ -269,7 +291,7 @@
         private void OnActiveSourceChanged (SourceEventArgs args)
         {
             Source source = ServiceManager.SourceManager.ActiveSource;
-            
+
             view_container.SearchSensitive = source != null && source.CanSearch;
             
             if (source == null) {
@@ -285,7 +307,7 @@
                 view_container.SearchEntry.Query = source.FilterQuery;
                 view_container.SearchEntry.ActivateFilter ((int)source.FilterType);
             }
-            
+
             // Clear any models previously connected to the views
             if (!(source is ITrackModelSource)) {
                 composite_view.SetModels (null, null, null);
@@ -298,8 +320,12 @@
             
             // Connect the source models to the views if possible
             if (source is ITrackModelSource) {
+                if (composite_view.TrackModel != null) {
+                    composite_view.TrackModel.Reloaded -= HandleTrackModelReloaded;
+                }
                 ITrackModelSource track_source = (ITrackModelSource)source;
                 composite_view.SetModels (track_source.TrackModel, track_source.ArtistModel, track_source.AlbumModel);
+                composite_view.TrackModel.Reloaded += HandleTrackModelReloaded;
                 composite_view.TrackView.HeaderVisible = true;
                 view_container.Content = composite_view;
             } else if (source is Hyena.Data.IObjectListModel) {
@@ -314,6 +340,7 @@
                 view_container.Content = object_view_scroll;
             }
             
+            UpdateStatusBar ();
             view_container.SearchEntry.Ready = true;
         }
         
@@ -453,6 +480,11 @@
 
 #region Helper Functions
 
+        private void HandleTrackModelReloaded (object sender, EventArgs args)
+        {
+            UpdateStatusBar ();
+        }
+
         private void SetPlaybackControllerSource (Source source)
         {
             // Set the source from which to play to the current source since
@@ -464,6 +496,16 @@
             ServiceManager.PlaybackController.Source = (ITrackModelSource)source;    
         }
 
+        private void UpdateStatusBar ()
+        {
+            if (ServiceManager.SourceManager.ActiveSource == null) {
+                status_label.Text = String.Empty;
+                return;
+            }
+
+            status_label.Text = ServiceManager.SourceManager.ActiveSource.GetStatusText ();
+        }
+
 #endregion
 
         string IService.ServiceName {



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