banshee r4187 - in trunk/banshee: . src/Core/Banshee.Core/Banshee.Collection src/Core/Banshee.Services src/Core/Banshee.Services/Banshee.Collection.Database src/Core/Banshee.Services/Banshee.Sources src/Core/Banshee.ThickClient src/Core/Banshee.ThickClient/Banshee.Collection.Gui src/Core/Banshee.ThickClient/Banshee.Sources.Gui src/Libraries/Hyena.Gui/Hyena.Data.Gui src/Libraries/Hyena.Gui/Hyena.Query.Gui src/Libraries/Hyena/Hyena.Data src/Libraries/Hyena/Hyena.Data.Sqlite src/Libraries/Hyena/Hyena.Query src/Libraries/Migo/Migo.Syndication



Author: gburt
Date: Mon Jun 23 17:56:52 2008
New Revision: 4187
URL: http://svn.gnome.org/viewvc/banshee?rev=4187&view=rev

Log:
2008-06-23  Gabriel Burt  <gabriel burt gmail com>

	* src/Core/Banshee.ThickClient/Banshee.Collection.Gui/ColumnCellQueryText.cs:
	New class that shows the Text of the object, or if blank, a given string.

	* src/Core/Banshee.ThickClient/Banshee.Collection.Gui/QueryFilterView.cs:
	A simple ListView derivative for showing a ColumnCellQueryText column.

	* src/Core/Banshee.ThickClient/Banshee.ThickClient.mdp:
	* src/Core/Banshee.ThickClient/Makefile.am: The new files above.

	* src/Core/Banshee.Services/Banshee.Sources/DatabaseSource.cs:
	* src/Core/Banshee.ThickClient/Banshee.Sources.Gui/CompositeTrackSourceContents.cs:
	Add a genre browser, hardcoded in for now (like artist/album).  We should
	make these configurable, rearrangable, etc.

	* src/Core/Banshee.Services/Banshee.Collection.Database/DatabaseQueryFilterModel.cs:
	Class that makes it very easy to have a new database-backed model for
	filters based on arbitrary columns from CoreTracks.  Currently used for
	the new genre browser.

	* src/Core/Banshee.Services/Banshee.Collection.Database/FilterModelProvider.cs:
	New class, derived from SqliteModelProvider, used for the new model
	mentioned above.  Overrides the Select statement so we'll be able to do
	things like "select distinct year/10" to get the decades of a track
	collection.

	* src/Core/Banshee.Services/Banshee.Collection.Database/QueryFilterInfo.cs:
	New class for each result row of the FilterModelProvider.  Holds the
	value, eg the decade in the above example, and has a settable Title.

	* src/Core/Banshee.Services/Banshee.Collection.Database/DatabaseFilterListModel.cs:
	Update FetchCount to 40, implement new CachesValues property, and don't
	require the connection be a BansheeDbConnection.

	* src/Core/Banshee.Services/Banshee.Collection.Database/DatabaseAlbumListModel.cs:
	* src/Core/Banshee.Services/Banshee.Collection.Database/DatabaseArtistListModel.cs:
	Tweak both reload SQL fragments for performance.

	* src/Libraries/Hyena/Hyena.Data.Sqlite/ICacheableDatabaseModel.cs:
	* src/Core/Banshee.Services/Banshee.Collection.Database/CachedList.cs:
	Add CachesValues property.

	* src/Core/Banshee.Services/Banshee.Collection.Database/DatabaseTrackListModel.cs:
	Implement CachesValues, and fix IndexOf to use new, improved
	cache.IndexOf.

	* src/Core/Banshee.Services/Banshee.Collection.Database/IDatabaseTrackModelCache.cs:
	Change IndexOf method to accept a ICacheableItem, and add an override that
	takes a cache_entry_id object.

	* src/Core/Banshee.Services/Banshee.Services.mdp:
	* src/Core/Banshee.Services/Makefile.am: Add new files.

	* src/Libraries/Migo/Migo.Syndication/MigoItem.cs:
	* src/Libraries/Hyena/Hyena.Data/ICacheableItem.cs:
	* src/Core/Banshee.Core/Banshee.Collection/CacheableItem.cs: CacheEntryId
	is now an object.

	* src/Libraries/Hyena/Hyena.Query/IntegerQueryValue.cs:
	* src/Libraries/Hyena/Hyena.Query/StringQueryValue.cs:
	* src/Libraries/Hyena/Hyena.Query/NullQueryValue.cs:
	* src/Libraries/Hyena/Hyena.Query/DateQueryValue.cs:
	* src/Libraries/Hyena/Hyena.Query/QueryValue.cs:
	* src/Libraries/Hyena/Hyena.Query/TimeSpanQueryValue.cs:
	* src/Libraries/Hyena/Hyena.Query/QueryField.cs: Add abstract LoadString
	method and implement in subclasses.  Also fix the
	NullQueryValue.IsNullOrEmpty operator.

	* src/Libraries/Hyena/Hyena.Data.Sqlite/SqliteModelProvider.cs: Add new
	AddColumn protected method so subclasses can manually define their
	columns.

	* src/Libraries/Hyena/Hyena.Data.Sqlite/DatabaseColumn.cs: Make classes
	public, not internal.

	* src/Libraries/Hyena/Hyena.Data.Sqlite/SqliteModelCache.cs: Implement new
	IndexOf methods, and check model.CachesValues, and if so, select straight
	out of the CoreCache table the stored distinct genre values, say.

	* src/Libraries/Hyena.Gui/Hyena.Data.Gui/IListView.cs: Expose the
	SelectionProxy.

	* src/Libraries/Hyena.Gui/Hyena.Query.Gui/StringQueryValueEntry.cs: Use
	ParseUserQuery instead of SetValue, since the input text is from the user.


Added:
   trunk/banshee/src/Core/Banshee.Services/Banshee.Collection.Database/DatabaseQueryFilterModel.cs
   trunk/banshee/src/Core/Banshee.Services/Banshee.Collection.Database/FilterModelProvider.cs
   trunk/banshee/src/Core/Banshee.Services/Banshee.Collection.Database/QueryFilterInfo.cs
   trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Collection.Gui/ColumnCellQueryText.cs
   trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Collection.Gui/QueryFilterView.cs
Modified:
   trunk/banshee/ChangeLog
   trunk/banshee/src/Core/Banshee.Core/Banshee.Collection/CacheableItem.cs
   trunk/banshee/src/Core/Banshee.Services/Banshee.Collection.Database/CachedList.cs
   trunk/banshee/src/Core/Banshee.Services/Banshee.Collection.Database/DatabaseAlbumListModel.cs
   trunk/banshee/src/Core/Banshee.Services/Banshee.Collection.Database/DatabaseArtistListModel.cs
   trunk/banshee/src/Core/Banshee.Services/Banshee.Collection.Database/DatabaseFilterListModel.cs
   trunk/banshee/src/Core/Banshee.Services/Banshee.Collection.Database/DatabaseTrackListModel.cs
   trunk/banshee/src/Core/Banshee.Services/Banshee.Collection.Database/IDatabaseTrackModelCache.cs
   trunk/banshee/src/Core/Banshee.Services/Banshee.Services.mdp
   trunk/banshee/src/Core/Banshee.Services/Banshee.Sources/DatabaseSource.cs
   trunk/banshee/src/Core/Banshee.Services/Makefile.am
   trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Sources.Gui/CompositeTrackSourceContents.cs
   trunk/banshee/src/Core/Banshee.ThickClient/Banshee.ThickClient.mdp
   trunk/banshee/src/Core/Banshee.ThickClient/Makefile.am
   trunk/banshee/src/Libraries/Hyena.Gui/Hyena.Data.Gui/IListView.cs
   trunk/banshee/src/Libraries/Hyena.Gui/Hyena.Query.Gui/StringQueryValueEntry.cs
   trunk/banshee/src/Libraries/Hyena/Hyena.Data.Sqlite/DatabaseColumn.cs
   trunk/banshee/src/Libraries/Hyena/Hyena.Data.Sqlite/ICacheableDatabaseModel.cs
   trunk/banshee/src/Libraries/Hyena/Hyena.Data.Sqlite/SqliteModelCache.cs
   trunk/banshee/src/Libraries/Hyena/Hyena.Data.Sqlite/SqliteModelProvider.cs
   trunk/banshee/src/Libraries/Hyena/Hyena.Data/ICacheableItem.cs
   trunk/banshee/src/Libraries/Hyena/Hyena.Query/DateQueryValue.cs
   trunk/banshee/src/Libraries/Hyena/Hyena.Query/IntegerQueryValue.cs
   trunk/banshee/src/Libraries/Hyena/Hyena.Query/NullQueryValue.cs
   trunk/banshee/src/Libraries/Hyena/Hyena.Query/QueryField.cs
   trunk/banshee/src/Libraries/Hyena/Hyena.Query/QueryValue.cs
   trunk/banshee/src/Libraries/Hyena/Hyena.Query/StringQueryValue.cs
   trunk/banshee/src/Libraries/Hyena/Hyena.Query/TimeSpanQueryValue.cs
   trunk/banshee/src/Libraries/Migo/Migo.Syndication/MigoItem.cs

Modified: trunk/banshee/src/Core/Banshee.Core/Banshee.Collection/CacheableItem.cs
==============================================================================
--- trunk/banshee/src/Core/Banshee.Core/Banshee.Collection/CacheableItem.cs	(original)
+++ trunk/banshee/src/Core/Banshee.Core/Banshee.Collection/CacheableItem.cs	Mon Jun 23 17:56:52 2008
@@ -37,8 +37,8 @@
     
 #region Implement ICacheableItem
 
-        private long cache_entry_id;
-        public long CacheEntryId {
+        private object cache_entry_id;
+        public object CacheEntryId {
             get { return cache_entry_id; }
             set { cache_entry_id = value; }
         }

Modified: trunk/banshee/src/Core/Banshee.Services/Banshee.Collection.Database/CachedList.cs
==============================================================================
--- trunk/banshee/src/Core/Banshee.Services/Banshee.Collection.Database/CachedList.cs	(original)
+++ trunk/banshee/src/Core/Banshee.Services/Banshee.Collection.Database/CachedList.cs	Mon Jun 23 17:56:52 2008
@@ -117,6 +117,7 @@
             public string JoinPrimaryKey { get { return null; } }
             public string JoinColumn { get { return null; } }
             public bool CachesJoinTableEntries { get { return false; } }
+            public bool CachesValues { get { return false; } }
             public Selection Selection { get { return null; } }
         }
     }

Modified: trunk/banshee/src/Core/Banshee.Services/Banshee.Collection.Database/DatabaseAlbumListModel.cs
==============================================================================
--- trunk/banshee/src/Core/Banshee.Services/Banshee.Collection.Database/DatabaseAlbumListModel.cs	(original)
+++ trunk/banshee/src/Core/Banshee.Services/Banshee.Collection.Database/DatabaseAlbumListModel.cs	Mon Jun 23 17:56:52 2008
@@ -46,12 +46,10 @@
             : base (source, trackModel, connection, DatabaseAlbumInfo.Provider, new AlbumInfo (null), uuid)
         {
             ReloadFragmentFormat = @"
-                FROM CoreAlbums INNER JOIN CoreArtists ON CoreAlbums.ArtistID = CoreArtists.ArtistID
-                    WHERE CoreAlbums.AlbumID IN
+                FROM CoreAlbums WHERE CoreAlbums.AlbumID IN
                         (SELECT CoreTracks.AlbumID FROM CoreTracks, CoreCache{0}
                             WHERE CoreCache.ModelID = {1} AND
-                                  CoreCache.ItemId = {2})
-                    {3}
+                                  CoreCache.ItemId = {2} {3})
                     ORDER BY CoreAlbums.TitleLowered, CoreAlbums.ArtistNameLowered";
         }
         

Modified: trunk/banshee/src/Core/Banshee.Services/Banshee.Collection.Database/DatabaseArtistListModel.cs
==============================================================================
--- trunk/banshee/src/Core/Banshee.Services/Banshee.Collection.Database/DatabaseArtistListModel.cs	(original)
+++ trunk/banshee/src/Core/Banshee.Services/Banshee.Collection.Database/DatabaseArtistListModel.cs	Mon Jun 23 17:56:52 2008
@@ -45,16 +45,15 @@
             : base (source, trackModel, connection, DatabaseArtistInfo.Provider, new ArtistInfo (null), uuid)
         {
             ReloadFragmentFormat = @"
-                FROM CoreArtists 
-                    WHERE CoreArtists.ArtistID IN
-                        (SELECT CoreTracks.ArtistID FROM CoreTracks, CoreCache{0}
-                            WHERE CoreCache.ModelID = {1} AND
-                                  CoreCache.ItemID = {2})
+                FROM CoreArtists WHERE CoreArtists.ArtistID IN
+                    (SELECT CoreTracks.ArtistID FROM CoreTracks, CoreCache{0}
+                        WHERE CoreCache.ModelID = {1} AND
+                              CoreCache.ItemID = {2} {3})
                     ORDER BY NameLowered";
         }
         
         public override string FilterColumn {
-            get { return "CoreArtists.ArtistID"; }
+            get { return "CoreTracks.ArtistID"; }
         }
         
         protected override string ItemToFilterValue (object item)

Modified: trunk/banshee/src/Core/Banshee.Services/Banshee.Collection.Database/DatabaseFilterListModel.cs
==============================================================================
--- trunk/banshee/src/Core/Banshee.Services/Banshee.Collection.Database/DatabaseFilterListModel.cs	(original)
+++ trunk/banshee/src/Core/Banshee.Services/Banshee.Collection.Database/DatabaseFilterListModel.cs	Mon Jun 23 17:56:52 2008
@@ -58,7 +58,7 @@
         
         protected readonly U select_all_item;
 
-        public DatabaseFilterListModel (Banshee.Sources.DatabaseSource source, DatabaseTrackListModel trackModel, BansheeDbConnection connection, SqliteModelProvider<T> provider, U selectAllItem, string uuid)
+        public DatabaseFilterListModel (Banshee.Sources.DatabaseSource source, DatabaseTrackListModel trackModel, HyenaSqliteConnection connection, SqliteModelProvider<T> provider, U selectAllItem, string uuid)
             : base (trackModel)
         {
             this.source = source;
@@ -112,6 +112,8 @@
             }
         }
         
+        public virtual bool CachesValues { get { return false; } }
+        
         protected abstract string ItemToFilterValue (object o);
 
         // Ick, duplicated from DatabaseTrackListModel
@@ -166,7 +168,7 @@
 
         // Implement ICacheableModel
         public virtual int FetchCount {
-            get { return 20; }
+            get { return 40; }
         }
 
         public virtual string SelectAggregates { get { return null; } }

Added: trunk/banshee/src/Core/Banshee.Services/Banshee.Collection.Database/DatabaseQueryFilterModel.cs
==============================================================================
--- (empty file)
+++ trunk/banshee/src/Core/Banshee.Services/Banshee.Collection.Database/DatabaseQueryFilterModel.cs	Mon Jun 23 17:56:52 2008
@@ -0,0 +1,122 @@
+//
+// DatabaseQueryFilterModel.cs
+//
+// Authors:
+//   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;
+using System.Text;
+using System.Reflection;
+
+using Hyena.Query;
+using Hyena.Data;
+using Hyena.Data.Sqlite;
+
+using Banshee.ServiceStack;
+
+namespace Banshee.Collection.Database
+{
+    public class DatabaseQueryFilterModel<T> : DatabaseFilterListModel<QueryFilterInfo<T>, QueryFilterInfo<T>>
+    {
+        private QueryField field;
+        private string select_all_fmt;
+
+        public DatabaseQueryFilterModel (Banshee.Sources.DatabaseSource source, DatabaseTrackListModel trackModel, 
+            HyenaSqliteConnection connection, string select_all_fmt, string uuid, QueryField field, string filter_column)
+            : base (source, trackModel, connection, QueryFilterInfo<T>.CreateProvider (filter_column, field), new QueryFilterInfo<T> (), String.Format ("{0}-{1}", uuid, field.Name))
+        {
+            this.field = field;
+            this.select_all_fmt = select_all_fmt;
+            
+            ReloadFragmentFormat = @"
+                FROM CoreTracks, CoreCache{0}
+                    WHERE CoreCache.ModelID = {1} AND CoreCache.ItemID = {2} {3}
+                    ORDER BY Value";
+        }
+        
+        public override bool CachesValues { get { return true; } }
+        
+        public override string GetSqlFilter ()
+        {
+            if (Selection.AllSelected)
+                return null;
+
+            StringBuilder sb = new StringBuilder ("(");
+            bool first = true;
+            //QueryListNode or = new QueryListNode (Keyword.Or);
+            foreach (object o in GetSelectedObjects ()) {
+                if (o != select_all_item) {
+                    string sql = null;
+                    QueryValue qv = QueryValue.CreateFromStringValue (o.ToString (), field);
+                    //QueryListNode and = new QueryListNode (Keyword.And, or);
+                    if (qv != null) {
+                        if (qv is IntegerQueryValue) {
+                            /*QueryTermNode term = new QueryTermNode ();
+                            term.Field = field;
+                            field.ToSql (IntegerQueryValue.GreaterThanEqual, qv);
+                            field.ToSql (IntegerQueryValue.GreaterThanEqual, qv);*/
+                        } else if (qv is StringQueryValue) {
+                            sql = field.ToSql (StringQueryValue.Equal, qv, true);
+                        }
+                    } else {
+                        sql = field.ToSql (NullQueryValue.IsNullOrEmpty, NullQueryValue.Instance, true);
+                    }
+                    
+                    if (sql != null) {
+                        if (first) {
+                            first = false;
+                        } else {
+                            sb.Append (" OR ");
+                        }
+                        sb.Append (sql);
+                    }
+                }
+            }
+            sb.Append (")");
+            return first ? null : sb.ToString ();
+        }
+        
+        protected override string ItemToFilterValue (object o)
+        {
+            throw new NotImplementedException ();
+        }
+        
+        public override string FilterColumn {
+            get { return String.Empty; }
+        }
+        
+        public override void UpdateSelectAllItem (long count)
+        {
+            select_all_item.Title = String.Format (select_all_fmt, count);
+        }
+    }
+    
+    /*public class DatabaseNumericQueryFilterModel<T> : DatabaseQueryFilterModel<T>
+    {
+        public DatabaseNumericQueryFilterModel (Banshee.Sources.DatabaseSource source, DatabaseTrackListModel trackModel, 
+            BansheeDbConnection connection, SqliteModelProvider<T> provider, U selectAllItem, string uuid, QueryField field)
+            : base (source, trackModel
+    }*/
+}

Modified: trunk/banshee/src/Core/Banshee.Services/Banshee.Collection.Database/DatabaseTrackListModel.cs
==============================================================================
--- trunk/banshee/src/Core/Banshee.Services/Banshee.Collection.Database/DatabaseTrackListModel.cs	(original)
+++ trunk/banshee/src/Core/Banshee.Services/Banshee.Collection.Database/DatabaseTrackListModel.cs	Mon Jun 23 17:56:52 2008
@@ -293,12 +293,7 @@
 
         public override int IndexOf (TrackInfo track)
         {
-            DatabaseTrackInfo db_track = track as DatabaseTrackInfo;
-            if (db_track == null || db_track.CacheModelId != CacheId) {
-                return -1;
-            }
-
-            return (int) cache.IndexOf ((int)db_track.CacheEntryId);
+            return (int) cache.IndexOf (track as DatabaseTrackInfo);
         }
 
         private DateTime random_began_at = DateTime.MinValue;
@@ -470,5 +465,7 @@
         public string ReloadFragment {
             get { return reload_fragment; }
         }
+        
+        public bool CachesValues { get { return false; } }
     }
 }

Added: trunk/banshee/src/Core/Banshee.Services/Banshee.Collection.Database/FilterModelProvider.cs
==============================================================================
--- (empty file)
+++ trunk/banshee/src/Core/Banshee.Services/Banshee.Collection.Database/FilterModelProvider.cs	Mon Jun 23 17:56:52 2008
@@ -0,0 +1,61 @@
+//
+// FilterModelProvider.cs
+//
+// Authors:
+//   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;
+using System.Reflection;
+
+using Hyena.Data.Sqlite;
+
+namespace Banshee.Collection.Database
+{
+    public class FilterModelProvider<T> : SqliteModelProvider<T> where T : new()
+    {
+        private string table_name;
+        
+        public FilterModelProvider (HyenaSqliteConnection conn, string table_name, string pk_column, PropertyInfo pk_info, string value_column, PropertyInfo value_info) : base (conn)
+        {
+            this.table_name = table_name;
+            PrimaryKey = pk_column;
+            
+            DatabaseColumnAttribute pk_attr = new DatabaseColumnAttribute ();
+            pk_attr.Constraints = DatabaseColumnConstraints.PrimaryKey;
+            AddColumn (new DatabaseColumn (pk_info, pk_attr), true);
+
+            AddColumn (new DatabaseColumn (value_info, new DatabaseColumnAttribute ()), true);
+            
+            select = String.Format ("ifnull({0}, '') as Value", value_column);
+        }
+        
+        public override string TableName { get { return table_name; } }
+        
+        private string select;
+        public override string Select {
+            get { return select; }
+        }
+    }
+}
\ No newline at end of file

Modified: trunk/banshee/src/Core/Banshee.Services/Banshee.Collection.Database/IDatabaseTrackModelCache.cs
==============================================================================
--- trunk/banshee/src/Core/Banshee.Services/Banshee.Collection.Database/IDatabaseTrackModelCache.cs	(original)
+++ trunk/banshee/src/Core/Banshee.Services/Banshee.Collection.Database/IDatabaseTrackModelCache.cs	Mon Jun 23 17:56:52 2008
@@ -42,7 +42,8 @@
         void RestoreSelection ();
         long Count { get; }
         void Reload ();
-        long IndexOf (long item_entry_id);
+        long IndexOf (Hyena.Data.ICacheableItem item);
+        long IndexOf (object item_entry_id);
         TrackInfo GetSingle (string random_fragment, params object [] args);
         TrackInfo GetValue (long index);
         long CacheId { get; }

Added: trunk/banshee/src/Core/Banshee.Services/Banshee.Collection.Database/QueryFilterInfo.cs
==============================================================================
--- (empty file)
+++ trunk/banshee/src/Core/Banshee.Services/Banshee.Collection.Database/QueryFilterInfo.cs	Mon Jun 23 17:56:52 2008
@@ -0,0 +1,78 @@
+//
+// QueryFilterInfo.cs
+//
+// Authors:
+//   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;
+using System.Reflection;
+
+using Hyena.Query;
+using Hyena.Data.Sqlite;
+
+using Banshee.ServiceStack;
+
+namespace Banshee.Collection.Database
+{
+    public class QueryFilterInfo<T> : CacheableItem
+    {
+        public static SqliteModelProvider<QueryFilterInfo<T>> CreateProvider (string filter_column, QueryField field)
+        {
+            SqliteModelProvider<QueryFilterInfo<T>> provider = new FilterModelProvider<QueryFilterInfo<T>> (
+                ServiceManager.DbConnection,
+                "CoreTracks",
+                "TrackID", typeof(QueryFilterInfo<T>).GetMember ("DbId")[0] as PropertyInfo,
+                filter_column, typeof(QueryFilterInfo<T>).GetMember ("Value")[0] as PropertyInfo
+            );
+                
+            return provider;
+        }
+        
+        private long dbid;
+        public long DbId {
+            get { return dbid; }
+            set { dbid = value; }
+        }
+
+        private T obj;
+        public T Value {
+            get { return obj; }
+            set { obj = value; }
+        }
+        
+        private string title;
+        public string Title {
+            get { return title ?? ToString (); }
+            set { title = value; }
+        }
+        
+        public object ValueObject { get { return Value; } }
+        
+        public override string ToString ()
+        {
+            return Value == null ? String.Empty : Value.ToString ();
+        }
+    }
+}

Modified: trunk/banshee/src/Core/Banshee.Services/Banshee.Services.mdp
==============================================================================
--- trunk/banshee/src/Core/Banshee.Services/Banshee.Services.mdp	(original)
+++ trunk/banshee/src/Core/Banshee.Services/Banshee.Services.mdp	Mon Jun 23 17:56:52 2008
@@ -174,6 +174,9 @@
     <File name="Banshee.ServiceStack/IDBusObjectName.cs" subtype="Code" buildaction="Compile" />
     <File name="Banshee.Hardware/IDiscDuplicator.cs" subtype="Code" buildaction="Compile" />
     <File name="Banshee.Collection.Database/DatabaseImportResultHandler.cs" subtype="Code" buildaction="Compile" />
+    <File name="Banshee.Collection.Database/DatabaseQueryFilterModel.cs" subtype="Code" buildaction="Compile" />
+    <File name="Banshee.Collection.Database/FilterModelProvider.cs" subtype="Code" buildaction="Compile" />
+    <File name="Banshee.Collection.Database/QueryFilterInfo.cs" subtype="Code" buildaction="Compile" />
   </Contents>
   <References>
     <ProjectReference type="Gac" localcopy="True" refto="System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />

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	Mon Jun 23 17:56:52 2008
@@ -54,6 +54,8 @@
         protected DatabaseTrackListModel track_model;
         protected DatabaseAlbumListModel album_model;
         protected DatabaseArtistListModel artist_model;
+        
+        private DatabaseQueryFilterModel<string> genre_model;
 
         protected RateLimiter reload_limiter;
         
@@ -109,6 +111,9 @@
             InitializeTrackModel ();
 
             if (HasArtistAlbum) {
+                genre_model = new Banshee.Collection.Database.DatabaseQueryFilterModel<string> (this, DatabaseTrackModel, ServiceManager.DbConnection,
+                    Catalog.GetString ("All Genres ({0})"), UniqueId, BansheeQuery.GenreField, "Genre");
+                
                 artist_model = new DatabaseArtistListModel (this, DatabaseTrackModel, ServiceManager.DbConnection, UniqueId);
                 album_model = new DatabaseAlbumListModel (this, DatabaseTrackModel, ServiceManager.DbConnection, UniqueId);
             }
@@ -224,6 +229,9 @@
         
         public virtual IEnumerable<IFilterListModel> FilterModels {
             get {
+                if (genre_model != null)
+                    yield return genre_model;
+
                 if (artist_model != null)
                     yield return artist_model;
                     
@@ -524,6 +532,9 @@
         {
             track_model.InvalidateCache ();
             
+            if (genre_model != null)
+                genre_model.InvalidateCache ();
+            
             // TODO invalidate cache on all FilterModels
             if (artist_model != null)
                 artist_model.InvalidateCache ();

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	Mon Jun 23 17:56:52 2008
@@ -13,12 +13,15 @@
 	Banshee.Collection.Database/DatabaseFilterListModel.cs \
 	Banshee.Collection.Database/DatabaseImportManager.cs \
 	Banshee.Collection.Database/DatabaseImportResultHandler.cs \
+	Banshee.Collection.Database/DatabaseQueryFilterModel.cs \
 	Banshee.Collection.Database/DatabaseTrackInfo.cs \
 	Banshee.Collection.Database/DatabaseTrackListModel.cs \
 	Banshee.Collection.Database/DatabaseTrackModelCache.cs \
 	Banshee.Collection.Database/DatabaseTrackModelProvider.cs \
+	Banshee.Collection.Database/FilterModelProvider.cs \
 	Banshee.Collection.Database/IDatabaseTrackModelCache.cs \
 	Banshee.Collection.Database/IDatabaseTrackModelProvider.cs \
+	Banshee.Collection.Database/QueryFilterInfo.cs \
 	Banshee.Collection/AlbumListModel.cs \
 	Banshee.Collection/ArtistListModel.cs \
 	Banshee.Collection/BansheeListModel.cs \

Added: trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Collection.Gui/ColumnCellQueryText.cs
==============================================================================
--- (empty file)
+++ trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Collection.Gui/ColumnCellQueryText.cs	Mon Jun 23 17:56:52 2008
@@ -0,0 +1,50 @@
+//
+// ColumnCellQueryText.cs
+//
+// Authors:
+//   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;
+
+using Hyena.Data.Gui;
+
+namespace Banshee.Collection.Gui
+{
+    public class ColumnCellQueryText : ColumnCellText
+    {
+        private string blank;
+        public ColumnCellQueryText (string blank, string property, bool expand) : base (property, expand)
+        {
+            this.blank = blank;
+        }
+        
+        protected override string Text {
+            get { 
+                string text = base.Text;
+                return String.IsNullOrEmpty (text) ? blank : text;
+            }
+        }
+    }
+}

Added: trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Collection.Gui/QueryFilterView.cs
==============================================================================
--- (empty file)
+++ trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Collection.Gui/QueryFilterView.cs	Mon Jun 23 17:56:52 2008
@@ -0,0 +1,49 @@
+//
+// QueryFilterView.cs
+//
+// Authors:
+//   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;
+
+using Hyena.Data.Gui;
+
+using Banshee.Collection.Database;
+
+namespace Banshee.Collection.Gui
+{
+    public class QueryFilterView<T> : TrackFilterListView<QueryFilterInfo<string>>
+    {
+        public QueryFilterView (string blank) : this (new Column ("Filter", new ColumnCellQueryText (blank, "Title", true), 1.0))
+        {
+        }
+
+        public QueryFilterView (Column column) : base ()
+        {
+            column_controller.Add (column);
+            ColumnController = column_controller;
+        }
+    }
+}

Modified: trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Sources.Gui/CompositeTrackSourceContents.cs
==============================================================================
--- trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Sources.Gui/CompositeTrackSourceContents.cs	(original)
+++ trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Sources.Gui/CompositeTrackSourceContents.cs	Mon Jun 23 17:56:52 2008
@@ -41,6 +41,7 @@
 using Banshee.Sources;
 using Banshee.ServiceStack;
 using Banshee.Collection;
+using Banshee.Collection.Database;
 using Banshee.Configuration;
 using Banshee.Gui;
 using Banshee.Collection.Gui;
@@ -49,6 +50,7 @@
 {
     public class CompositeTrackSourceContents : FilteredListSourceContents, ITrackModelSourceContents
     {
+        private QueryFilterView<string> genre_view;
         private ArtistListView artist_view;
         private AlbumListView album_view;
         private TrackListView track_view;
@@ -60,12 +62,16 @@
         protected override void InitializeViews ()
         {
             SetupMainView (track_view = new TrackListView ());
+            SetupFilterView (genre_view = new QueryFilterView<string> (Catalog.GetString ("Not Set")));
             SetupFilterView (artist_view = new ArtistListView ());
             SetupFilterView (album_view = new AlbumListView ());
         }
         
         protected override void ClearFilterSelections ()
         {
+            if (genre_view.Model != null) {
+                genre_view.Selection.Clear ();
+            }
             if (artist_view.Model != null) {
                 artist_view.Selection.Clear ();
             }
@@ -74,11 +80,12 @@
             }
         }
 
-        public void SetModels (TrackListModel track, IListModel<ArtistInfo> artist, IListModel<AlbumInfo> album)
+        public void SetModels (TrackListModel track, IListModel<ArtistInfo> artist, IListModel<AlbumInfo> album, IListModel<QueryFilterInfo<string>> genre)
         {
             SetModel (track);
             SetModel (artist);
             SetModel (album);
+            SetModel (genre);
         }
         
         IListView<TrackInfo> ITrackModelSourceContents.TrackView {
@@ -146,6 +153,8 @@
                     SetModel (artist_view, (model as IListModel<ArtistInfo>));
                 else if (model is IListModel<AlbumInfo>)
                     SetModel (album_view, (model as IListModel<AlbumInfo>));
+                else if (model is IListModel<QueryFilterInfo<string>>)
+                    SetModel (genre_view, (model as IListModel<QueryFilterInfo<string>>));
                 else
                     Hyena.Log.DebugFormat ("CompositeTrackSourceContents got non-album/artist filter model: {0}", model);
             }
@@ -162,6 +171,7 @@
             track_view.SetModel (null);
             artist_view.SetModel (null);
             album_view.SetModel (null);
+            genre_view.SetModel (null);
             track_view.HeaderVisible = false;
             //Console.WriteLine ("CTSC.reset_source 2");
         }

Modified: trunk/banshee/src/Core/Banshee.ThickClient/Banshee.ThickClient.mdp
==============================================================================
--- trunk/banshee/src/Core/Banshee.ThickClient/Banshee.ThickClient.mdp	(original)
+++ trunk/banshee/src/Core/Banshee.ThickClient/Banshee.ThickClient.mdp	Mon Jun 23 17:56:52 2008
@@ -115,6 +115,8 @@
     <File name="Banshee.Collection.Gui/DefaultColumnController.cs" subtype="Code" buildaction="Compile" />
     <File name="Banshee.Collection.Gui/XmlColumnController.cs" subtype="Code" buildaction="Compile" />
     <File name="Banshee.Gui/IClientWindow.cs" subtype="Code" buildaction="Compile" />
+    <File name="Banshee.Collection.Gui/ColumnCellQueryText.cs" subtype="Code" buildaction="Compile" />
+    <File name="Banshee.Collection.Gui/QueryFilterView.cs" subtype="Code" buildaction="Compile" />
   </Contents>
   <References>
     <ProjectReference type="Project" localcopy="False" refto="Hyena.Gui" />

Modified: trunk/banshee/src/Core/Banshee.ThickClient/Makefile.am
==============================================================================
--- trunk/banshee/src/Core/Banshee.ThickClient/Makefile.am	(original)
+++ trunk/banshee/src/Core/Banshee.ThickClient/Makefile.am	Mon Jun 23 17:56:52 2008
@@ -16,11 +16,13 @@
 	Banshee.Collection.Gui/ColumnCellDuration.cs \
 	Banshee.Collection.Gui/ColumnCellFileSize.cs \
 	Banshee.Collection.Gui/ColumnCellPositiveInt.cs \
+	Banshee.Collection.Gui/ColumnCellQueryText.cs \
 	Banshee.Collection.Gui/ColumnCellStatusIndicator.cs \
 	Banshee.Collection.Gui/ColumnCellTrack.cs \
 	Banshee.Collection.Gui/ColumnCellTrackNumber.cs \
 	Banshee.Collection.Gui/DefaultColumnController.cs \
 	Banshee.Collection.Gui/PersistentColumnController.cs \
+	Banshee.Collection.Gui/QueryFilterView.cs \
 	Banshee.Collection.Gui/TerseTrackListView.cs \
 	Banshee.Collection.Gui/TrackFilterListView.cs \
 	Banshee.Collection.Gui/TrackListView.cs \

Modified: trunk/banshee/src/Libraries/Hyena.Gui/Hyena.Data.Gui/IListView.cs
==============================================================================
--- trunk/banshee/src/Libraries/Hyena.Gui/Hyena.Data.Gui/IListView.cs	(original)
+++ trunk/banshee/src/Libraries/Hyena.Gui/Hyena.Data.Gui/IListView.cs	Mon Jun 23 17:56:52 2008
@@ -30,6 +30,7 @@
 {
     public interface IListView
     {
+        Hyena.Collections.SelectionProxy SelectionProxy { get; }
         Hyena.Collections.Selection Selection { get; }
         
         void ScrollTo (int index);

Modified: trunk/banshee/src/Libraries/Hyena.Gui/Hyena.Query.Gui/StringQueryValueEntry.cs
==============================================================================
--- trunk/banshee/src/Libraries/Hyena.Gui/Hyena.Query.Gui/StringQueryValueEntry.cs	(original)
+++ trunk/banshee/src/Libraries/Hyena.Gui/Hyena.Query.Gui/StringQueryValueEntry.cs	Mon Jun 23 17:56:52 2008
@@ -58,7 +58,7 @@
 
         protected void HandleChanged (object o, EventArgs args)
         {
-            query_value.SetValue (entry.Text);
+            query_value.ParseUserQuery (entry.Text);
         }
     }
 }

Modified: trunk/banshee/src/Libraries/Hyena/Hyena.Data.Sqlite/DatabaseColumn.cs
==============================================================================
--- trunk/banshee/src/Libraries/Hyena/Hyena.Data.Sqlite/DatabaseColumn.cs	(original)
+++ trunk/banshee/src/Libraries/Hyena/Hyena.Data.Sqlite/DatabaseColumn.cs	Mon Jun 23 17:56:52 2008
@@ -33,7 +33,7 @@
 
 namespace Hyena.Data.Sqlite
 {
-    internal abstract class AbstractDatabaseColumn
+    public abstract class AbstractDatabaseColumn
     {
         private readonly FieldInfo field_info;
         private readonly PropertyInfo property_info;
@@ -111,7 +111,7 @@
         }
     }
     
-    internal sealed class DatabaseColumn : AbstractDatabaseColumn
+    public sealed class DatabaseColumn : AbstractDatabaseColumn
     {
         private DatabaseColumnAttribute attribute;
         

Modified: trunk/banshee/src/Libraries/Hyena/Hyena.Data.Sqlite/ICacheableDatabaseModel.cs
==============================================================================
--- trunk/banshee/src/Libraries/Hyena/Hyena.Data.Sqlite/ICacheableDatabaseModel.cs	(original)
+++ trunk/banshee/src/Libraries/Hyena/Hyena.Data.Sqlite/ICacheableDatabaseModel.cs	Mon Jun 23 17:56:52 2008
@@ -41,5 +41,6 @@
         string JoinPrimaryKey { get; }
         string JoinColumn { get; }
         bool CachesJoinTableEntries { get; }
+        bool CachesValues { get; }
     }
 }

Modified: trunk/banshee/src/Libraries/Hyena/Hyena.Data.Sqlite/SqliteModelCache.cs
==============================================================================
--- trunk/banshee/src/Libraries/Hyena/Hyena.Data.Sqlite/SqliteModelCache.cs	(original)
+++ trunk/banshee/src/Libraries/Hyena/Hyena.Data.Sqlite/SqliteModelCache.cs	Mon Jun 23 17:56:52 2008
@@ -121,6 +121,17 @@
                         INSERT INTO {0} (ModelID, ItemID) SELECT {1}, {2} ",
                     CacheTableName, uid, model.JoinPrimaryKey
                 );
+            } else if (model.CachesValues) {
+                select_str = String.Format (
+                    @"SELECT OrderID, ItemID FROM {0} WHERE {0}.ModelID = {1}",
+                    CacheTableName, uid
+                );
+                
+                reload_sql = String.Format (@"
+                    DELETE FROM {0} WHERE ModelID = {1};
+                    INSERT INTO {0} (ModelID, ItemID) SELECT DISTINCT {1}, {2} ",
+                    CacheTableName, uid, provider.Select
+                );
             } else {
                 select_str = String.Format (
                     @"SELECT {0}, {2}.ItemID FROM {1}
@@ -217,8 +228,16 @@
              }
         }
         
-        // FIXME this should really take a type T, not a confusing, ambiguous long
-        public long IndexOf (long item_id)
+        public long IndexOf (ICacheableItem item)
+        {
+            if (item == null || item.CacheModelId != CacheId) {
+                return -1;
+            }
+            
+            return IndexOf (item.CacheEntryId);
+        }
+
+        public long IndexOf (object item_id)
         {
             lock (this) {
                 if (rows == 0) {
@@ -247,7 +266,7 @@
             using (IDataReader reader = connection.Query (get_single_command, args)) {
                 if (reader.Read ()) {
                     T item = provider.Load (reader);
-                    item.CacheEntryId = Convert.ToInt64 (reader[reader.FieldCount - 1]);
+                    item.CacheEntryId = reader[reader.FieldCount - 1];
                     item.CacheModelId = uid;
                     return item;
                 }
@@ -287,7 +306,7 @@
         }
 
         private bool saved_selection = false;
-        private long saved_focus_entry_id = -1;
+        private ICacheableItem saved_focus_item = null;
         public void SaveSelection ()
         {
             if (model.Selection != null && model.Selection.Count > 0 &&
@@ -299,7 +318,7 @@
                 if (!has_select_all_item && model.Selection.FocusedIndex != -1) {
                     T item = GetValue (model.Selection.FocusedIndex);
                     if (item != null) {
-                        saved_focus_entry_id = (int) GetValue (model.Selection.FocusedIndex).CacheEntryId;
+                        saved_focus_item = GetValue (model.Selection.FocusedIndex);
                     }
                 }
 
@@ -343,15 +362,15 @@
 
                 if (has_select_all_item && model.Selection.Count == 0) {
                     model.Selection.QuietSelect (0);
-                } if (saved_focus_entry_id != -1) {
-                    long i = IndexOf (saved_focus_entry_id);
+                } if (saved_focus_item != null) {
+                    long i = IndexOf (saved_focus_item);
                     if (i != -1) {
                         // TODO get rid of int cast
                         model.Selection.FocusedIndex = (int)i;
                     }
                 }
                 saved_selection = false;
-                saved_focus_entry_id = -1;
+                saved_focus_item = null;
             }
         }
 
@@ -363,7 +382,7 @@
                     while (reader.Read ()) {
                         if (!ContainsKey (offset)) {
                             item = provider.Load (reader);
-                            item.CacheEntryId = Convert.ToInt64 (reader[reader.FieldCount - 1]);
+                            item.CacheEntryId = reader[reader.FieldCount - 1];
                             item.CacheModelId = uid;
                             Add (offset, item);
                         }

Modified: trunk/banshee/src/Libraries/Hyena/Hyena.Data.Sqlite/SqliteModelProvider.cs
==============================================================================
--- trunk/banshee/src/Libraries/Hyena/Hyena.Data.Sqlite/SqliteModelProvider.cs	(original)
+++ trunk/banshee/src/Libraries/Hyena/Hyena.Data.Sqlite/SqliteModelProvider.cs	Mon Jun 23 17:56:52 2008
@@ -213,36 +213,8 @@
                 DatabaseColumn c = member is FieldInfo
                     ? new DatabaseColumn ((FieldInfo)member, column)
                     : new DatabaseColumn ((PropertyInfo)member, column);
-                
-                foreach (DatabaseColumn col in columns) {
-                    if (col.Name == c.Name) {
-                        throw new Exception (String.Format (
-                            "{0} has multiple columns named {1}",
-                             TableName, c.Name)
-                        );
-                    }
-                    if (col.Index != null && col.Index == c.Index) {
-                        throw new Exception (String.Format (
-                            "{0} has multiple indecies named {1}",
-                            TableName, c.Name)
-                        );
-                    }
-                }
-                
-                columns.Add (c);
-
-                if (column.Select) {
-                    select_columns.Add (c);
-                }
-                
-                if ((c.Constraints & DatabaseColumnConstraints.PrimaryKey) > 0) {
-                    if (key != null) {
-                        throw new Exception (String.Format (
-                            "Multiple primary keys in the {0} table", TableName)
-                        );
-                    }
-                    key = c;
-                }
+                    
+                AddColumn (c, column.Select);
             }
             VirtualDatabaseColumnAttribute virtual_column = attribute as VirtualDatabaseColumnAttribute;
             if (virtual_column != null) {
@@ -254,6 +226,39 @@
             }
         }
         
+        protected void AddColumn (DatabaseColumn c, bool select)
+        {
+            foreach (DatabaseColumn col in columns) {
+                if (col.Name == c.Name) {
+                    throw new Exception (String.Format (
+                        "{0} has multiple columns named {1}",
+                         TableName, c.Name)
+                    );
+                }
+                if (col.Index != null && col.Index == c.Index) {
+                    throw new Exception (String.Format (
+                        "{0} has multiple indecies named {1}",
+                        TableName, c.Name)
+                    );
+                }
+            }
+            
+            columns.Add (c);
+
+            if (select) {
+                select_columns.Add (c);
+            }
+            
+            if ((c.Constraints & DatabaseColumnConstraints.PrimaryKey) > 0) {
+                if (key != null) {
+                    throw new Exception (String.Format (
+                        "Multiple primary keys in the {0} table", TableName)
+                    );
+                }
+                key = c;
+            }
+        }
+        
         protected virtual void CreateTable ()
         {
             connection.Execute (CreateCommand);
@@ -643,6 +648,7 @@
                 }
                 return primary_key;
             }
+            protected set { primary_key = value; }
         }
         
         private void BuildQuerySql ()

Modified: trunk/banshee/src/Libraries/Hyena/Hyena.Data/ICacheableItem.cs
==============================================================================
--- trunk/banshee/src/Libraries/Hyena/Hyena.Data/ICacheableItem.cs	(original)
+++ trunk/banshee/src/Libraries/Hyena/Hyena.Data/ICacheableItem.cs	Mon Jun 23 17:56:52 2008
@@ -32,7 +32,7 @@
 {
     public interface ICacheableItem
     {
-        long CacheEntryId { get; set; }
+        object CacheEntryId { get; set; }
         long CacheModelId { get; set; }
     }
 }

Modified: trunk/banshee/src/Libraries/Hyena/Hyena.Query/DateQueryValue.cs
==============================================================================
--- trunk/banshee/src/Libraries/Hyena/Hyena.Query/DateQueryValue.cs	(original)
+++ trunk/banshee/src/Libraries/Hyena/Hyena.Query/DateQueryValue.cs	Mon Jun 23 17:56:52 2008
@@ -88,7 +88,7 @@
             IsEmpty = false;
         }
 
-        public void LoadString (string val, bool isRelative)
+        public override void LoadString (string val)
         {
             try {
                 SetValue (DateTime.Parse (val));
@@ -100,7 +100,7 @@
         public override void ParseXml (XmlElement node)
         {
             try {
-                LoadString (node.InnerText, node.HasAttribute ("type") && node.GetAttribute ("type") == "rel");
+                LoadString (node.InnerText);
             } catch {
                 IsEmpty = true;
             }

Modified: trunk/banshee/src/Libraries/Hyena/Hyena.Query/IntegerQueryValue.cs
==============================================================================
--- trunk/banshee/src/Libraries/Hyena/Hyena.Query/IntegerQueryValue.cs	(original)
+++ trunk/banshee/src/Libraries/Hyena/Hyena.Query/IntegerQueryValue.cs	Mon Jun 23 17:56:52 2008
@@ -53,6 +53,11 @@
         {
             IsEmpty = !Int64.TryParse (input, out value);
         }
+        
+        public override void LoadString (string input)
+        {
+            ParseUserQuery (input);
+        }
 
         public override void ParseXml (XmlElement node)
         {

Modified: trunk/banshee/src/Libraries/Hyena/Hyena.Query/NullQueryValue.cs
==============================================================================
--- trunk/banshee/src/Libraries/Hyena/Hyena.Query/NullQueryValue.cs	(original)
+++ trunk/banshee/src/Libraries/Hyena/Hyena.Query/NullQueryValue.cs	Mon Jun 23 17:56:52 2008
@@ -36,7 +36,9 @@
 {
     public class NullQueryValue : QueryValue
     {
-        public static readonly Operator IsNullOrEmpty  = new Operator ("empty", "IS NULL", "!");
+        public static readonly Operator IsNullOrEmpty  = new Operator ("empty", "IN (NULL, '', 0)", true, "!");
+        
+        public static readonly NullQueryValue Instance = new NullQueryValue ();
 
         public override string XmlElementName {
             get { return "empty"; }
@@ -51,7 +53,7 @@
             get { return operators; }
         }
 
-        public NullQueryValue ()
+        private NullQueryValue ()
         {
             IsEmpty = false;
         }
@@ -59,6 +61,10 @@
         public override void ParseUserQuery (string input)
         {
         }
+        
+        public override void LoadString (string input)
+        {
+        }
 
         public override void ParseXml (XmlElement node)
         {

Modified: trunk/banshee/src/Libraries/Hyena/Hyena.Query/QueryField.cs
==============================================================================
--- trunk/banshee/src/Libraries/Hyena/Hyena.Query/QueryField.cs	(original)
+++ trunk/banshee/src/Libraries/Hyena/Hyena.Query/QueryField.cs	Mon Jun 23 17:56:52 2008
@@ -130,7 +130,12 @@
 
         public string ToSql (Operator op, QueryValue qv)
         {
-            string value = qv.ToSql ();
+            return ToSql (op, qv, false);
+        }
+        
+        public string ToSql (Operator op, QueryValue qv, bool caseSensitive)
+        {
+            string value = qv.ToSql () ?? String.Empty;
 
             if (op == null) op = qv.OperatorSet.First;
 
@@ -138,8 +143,8 @@
 
             if (no_custom_format) {
                 if (qv is StringQueryValue) {
-                    if (column_lowered) {
-                        // The column is pre-lowered, only no need to call lower() in SQL
+                    if (column_lowered || !caseSensitive) {
+                        // The column is pre-lowered, no need to call lower() in SQL
                         sb.AppendFormat ("{0} {1}", Column, String.Format (op.SqlFormat, value.ToLower ()));
                     } else {
                         // Match string values literally and against a lower'd version.  Mostly a workaround

Modified: trunk/banshee/src/Libraries/Hyena/Hyena.Query/QueryValue.cs
==============================================================================
--- trunk/banshee/src/Libraries/Hyena/Hyena.Query/QueryValue.cs	(original)
+++ trunk/banshee/src/Libraries/Hyena/Hyena.Query/QueryValue.cs	Mon Jun 23 17:56:52 2008
@@ -62,6 +62,24 @@
 
             return null;
         }
+        
+        public static QueryValue CreateFromStringValue (string input, QueryField field)
+        {
+            if (field == null) {
+                QueryValue val = new StringQueryValue ();
+                val.LoadString (input);
+                return val;
+            } else {
+                foreach (QueryValue val in field.CreateQueryValues ()) {
+                    val.LoadString (input);
+                    if (!val.IsEmpty) {
+                        return val;
+                    }
+                }
+            }
+
+            return null;
+        }
 
         public static QueryValue CreateFromXml (XmlElement parent, QueryField field)
         {
@@ -103,6 +121,7 @@
         public abstract string XmlElementName { get; }
         public abstract AliasedObjectSet<Operator> OperatorSet { get; }
 
+        public abstract void LoadString (string input);
         public abstract void ParseXml (XmlElement node);
 
         public virtual void AppendXml (XmlElement node)

Modified: trunk/banshee/src/Libraries/Hyena/Hyena.Query/StringQueryValue.cs
==============================================================================
--- trunk/banshee/src/Libraries/Hyena/Hyena.Query/StringQueryValue.cs	(original)
+++ trunk/banshee/src/Libraries/Hyena/Hyena.Query/StringQueryValue.cs	Mon Jun 23 17:56:52 2008
@@ -70,10 +70,9 @@
             IsEmpty = String.IsNullOrEmpty (value);
         }
 
-        public void SetValue (string str)
+        public override void LoadString (string str)
         {
-            value = str;
-            IsEmpty = String.IsNullOrEmpty (value);
+            ParseUserQuery (str);
         }
 
         public override string ToSql ()

Modified: trunk/banshee/src/Libraries/Hyena/Hyena.Query/TimeSpanQueryValue.cs
==============================================================================
--- trunk/banshee/src/Libraries/Hyena/Hyena.Query/TimeSpanQueryValue.cs	(original)
+++ trunk/banshee/src/Libraries/Hyena/Hyena.Query/TimeSpanQueryValue.cs	Mon Jun 23 17:56:52 2008
@@ -121,7 +121,7 @@
             IsEmpty = false;
         }
 
-        public void LoadString (string val)
+        public override void LoadString (string val)
         {
             try {
                 SetRelativeValue (Convert.ToDouble (val), TimeFactor.Second);

Modified: trunk/banshee/src/Libraries/Migo/Migo.Syndication/MigoItem.cs
==============================================================================
--- trunk/banshee/src/Libraries/Migo/Migo.Syndication/MigoItem.cs	(original)
+++ trunk/banshee/src/Libraries/Migo/Migo.Syndication/MigoItem.cs	Mon Jun 23 17:56:52 2008
@@ -37,8 +37,8 @@
     // This class is generic b/c of some ideas that I didn't implement yet...could be made non-generic
     public abstract class MigoItem<T> : ICacheableItem
     {
-        private long cache_entry_id;
-        public long CacheEntryId {
+        private object cache_entry_id;
+        public object CacheEntryId {
             get { return cache_entry_id; }
             set { cache_entry_id = value; }
         }



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