[banshee] Add a year filter to the browser (bgo#540873)
- From: Alexander Kojevnikov <alexk src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [banshee] Add a year filter to the browser (bgo#540873)
- Date: Sun, 6 Nov 2011 12:28:23 +0000 (UTC)
commit e357e79e85754c5df0f3b59b4973dc7b5d86981e
Author: Frank Ziegler <funtastix googlemail com>
Date: Sun Nov 6 20:26:17 2011 +0800
Add a year filter to the browser (bgo#540873)
Signed-off-by: Alexander Kojevnikov <alexk gnome org>
.../Banshee.Core/Banshee.Collection/YearInfo.cs | 63 ++++++++++++++++++
src/Core/Banshee.Core/Banshee.Core.csproj | 1 +
src/Core/Banshee.Core/Makefile.am | 1 +
.../DatabaseYearInfo.cs | 66 +++++++++++++++++++
.../DatabaseYearListModel.cs | 69 ++++++++++++++++++++
src/Core/Banshee.Services/Banshee.Services.csproj | 2 +
.../Banshee.Sources/DatabaseSource.cs | 2 +
src/Core/Banshee.Services/Makefile.am | 2 +
.../Banshee.Collection.Gui/YearListView.cs | 49 ++++++++++++++
.../CompositeTrackSourceContents.cs | 46 +++++++++++++-
.../Banshee.ThickClient/Banshee.ThickClient.csproj | 1 +
src/Core/Banshee.ThickClient/Makefile.am | 1 +
12 files changed, 302 insertions(+), 1 deletions(-)
---
diff --git a/src/Core/Banshee.Core/Banshee.Collection/YearInfo.cs b/src/Core/Banshee.Core/Banshee.Collection/YearInfo.cs
new file mode 100644
index 0000000..5dc9136
--- /dev/null
+++ b/src/Core/Banshee.Core/Banshee.Collection/YearInfo.cs
@@ -0,0 +1,63 @@
+//
+// YearInfo.cs
+//
+// Author:
+// Frank Ziegler <funtastix googlemail com>
+//
+// 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.RegularExpressions;
+using Mono.Unix;
+
+using Hyena;
+using Banshee.Base;
+
+namespace Banshee.Collection
+{
+ public class YearInfo : CacheableItem
+ {
+ public static readonly string UnknownYearTitle = Catalog.GetString ("Unknown Year");
+
+ private int year;
+
+ public YearInfo ()
+ {
+ }
+
+ private string name;
+ public virtual string Name {
+ get {
+ if (String.IsNullOrEmpty (name))
+ return Year == 0 ? UnknownYearTitle : Year.ToString ();
+ else
+ return name;
+ }
+ set { name = value; }
+ }
+
+ public virtual int Year {
+ get { return year; }
+ set { year = value; }
+ }
+
+ }
+}
diff --git a/src/Core/Banshee.Core/Banshee.Core.csproj b/src/Core/Banshee.Core/Banshee.Core.csproj
index 038ca77..ac0a159 100644
--- a/src/Core/Banshee.Core/Banshee.Core.csproj
+++ b/src/Core/Banshee.Core/Banshee.Core.csproj
@@ -140,6 +140,7 @@
<Compile Include="Banshee.Base\Tests\CoverArtSpecTests.cs" />
<Compile Include="Banshee.Collection\IPodcastInfo.cs" />
<Compile Include="Banshee.IO\Tests.cs" />
+ <Compile Include="Banshee.Collection\YearInfo.cs" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="Resources\contributors.xml">
diff --git a/src/Core/Banshee.Core/Makefile.am b/src/Core/Banshee.Core/Makefile.am
index 3c8de92..229d783 100644
--- a/src/Core/Banshee.Core/Makefile.am
+++ b/src/Core/Banshee.Core/Makefile.am
@@ -25,6 +25,7 @@ SOURCES = \
Banshee.Collection/TrackInfo.cs \
Banshee.Collection/TrackMediaAttributes.cs \
Banshee.Collection/UnknownTrackInfo.cs \
+ Banshee.Collection/YearInfo.cs \
Banshee.Configuration.Schema/ImportSchema.cs \
Banshee.Configuration/ConfigurationClient.cs \
Banshee.Configuration/IConfigurationClient.cs \
diff --git a/src/Core/Banshee.Services/Banshee.Collection.Database/DatabaseYearInfo.cs b/src/Core/Banshee.Services/Banshee.Collection.Database/DatabaseYearInfo.cs
new file mode 100644
index 0000000..687062e
--- /dev/null
+++ b/src/Core/Banshee.Services/Banshee.Collection.Database/DatabaseYearInfo.cs
@@ -0,0 +1,66 @@
+//
+// DatabaseYearInfo.cs
+//
+// Author:
+// Frank Ziegler <funtastix googlemail com>
+//
+// 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 Mono.Unix;
+
+using Hyena.Data;
+using Hyena.Data.Sqlite;
+
+using Banshee.Database;
+using Banshee.ServiceStack;
+
+namespace Banshee.Collection.Database
+{
+ public class DatabaseYearInfo : YearInfo
+ {
+ private static BansheeModelProvider<DatabaseYearInfo> provider = new BansheeModelProvider<DatabaseYearInfo> (
+ ServiceManager.DbConnection, "CoreTracks"
+ );
+
+ public static BansheeModelProvider<DatabaseYearInfo> Provider {
+ get { return provider; }
+ }
+
+ public DatabaseYearInfo ()
+ {
+ }
+
+ private int track_id;
+ [DatabaseColumn ("TrackID", Constraints = DatabaseColumnConstraints.PrimaryKey)]
+ public int TrackId {
+ get { return track_id; }
+ protected set { track_id = value; }
+ }
+
+ [DatabaseColumn("Year")]
+ private int year;
+ public override int Year {
+ get { return year; }
+ }
+ }
+}
diff --git a/src/Core/Banshee.Services/Banshee.Collection.Database/DatabaseYearListModel.cs b/src/Core/Banshee.Services/Banshee.Collection.Database/DatabaseYearListModel.cs
new file mode 100644
index 0000000..b58d1df
--- /dev/null
+++ b/src/Core/Banshee.Services/Banshee.Collection.Database/DatabaseYearListModel.cs
@@ -0,0 +1,69 @@
+//
+// DatabaseYearListModel.cs
+//
+// Author:
+// Frank Ziegler <funtastix googlemail com>
+//
+// 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.Collections.Generic;
+using Mono.Unix;
+
+using Hyena;
+using Hyena.Data.Sqlite;
+using Hyena.Query;
+
+using Banshee.Database;
+
+namespace Banshee.Collection.Database
+{
+ public class DatabaseYearListModel : DatabaseFilterListModel<DatabaseYearInfo, YearInfo>
+ {
+ public DatabaseYearListModel (Banshee.Sources.DatabaseSource source, DatabaseTrackListModel trackModel, BansheeDbConnection connection, string uuid)
+ : base (Banshee.Query.BansheeQuery.YearField.Name, Banshee.Query.BansheeQuery.YearField.Label,
+ source, trackModel, connection, DatabaseYearInfo.Provider, new YearInfo (), uuid)
+ {
+ QueryFields = new QueryFieldSet (Banshee.Query.BansheeQuery.YearField);
+ ReloadFragmentFormat = @"
+ FROM (SELECT MIN(CoreTracks.TrackID) AS TrackID, CoreTracks.Year FROM CoreTracks GROUP BY CoreTracks.Year) AS CoreTracks
+ WHERE CoreTracks.Year IN
+ (SELECT CoreTracks.Year FROM CoreTracks, CoreCache{0}
+ WHERE CoreCache.ModelID = {1} AND
+ CoreCache.ItemID = {2} {3})
+ ORDER BY Year";
+ }
+
+ public override string FilterColumn {
+ get { return "CoreTracks.Year"; }
+ }
+
+ protected override string ItemToFilterValue (object item)
+ {
+ return (item is DatabaseYearInfo) ? (item as DatabaseYearInfo).Year.ToString () : null;
+ }
+
+ public override void UpdateSelectAllItem (long count)
+ {
+ select_all_item.Name = String.Format (Catalog.GetString ("All Years ({0})"), count);
+ }
+ }
+}
diff --git a/src/Core/Banshee.Services/Banshee.Services.csproj b/src/Core/Banshee.Services/Banshee.Services.csproj
index 3484a6e..5d4f875 100644
--- a/src/Core/Banshee.Services/Banshee.Services.csproj
+++ b/src/Core/Banshee.Services/Banshee.Services.csproj
@@ -324,6 +324,8 @@
<Compile Include="Banshee.Query\Tests\BansheeQueryTests.cs" />
<Compile Include="Banshee.Collection.Database\DatabaseAlbumArtistInfo.cs" />
<Compile Include="Banshee.Collection.Database\DatabaseAlbumArtistListModel.cs" />
+ <Compile Include="Banshee.Collection.Database\DatabaseYearInfo.cs" />
+ <Compile Include="Banshee.Collection.Database\DatabaseYearListModel.cs" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="Banshee.Services.addin.xml">
diff --git a/src/Core/Banshee.Services/Banshee.Sources/DatabaseSource.cs b/src/Core/Banshee.Services/Banshee.Sources/DatabaseSource.cs
index c67a14c..b9b0a1f 100644
--- a/src/Core/Banshee.Services/Banshee.Sources/DatabaseSource.cs
+++ b/src/Core/Banshee.Services/Banshee.Sources/DatabaseSource.cs
@@ -147,6 +147,7 @@ namespace Banshee.Sources
DatabaseAlbumListModel album_model = new DatabaseAlbumListModel (src, src.DatabaseTrackModel, ServiceManager.DbConnection, src.UniqueId);
DatabaseQueryFilterModel<string> genre_model = new DatabaseQueryFilterModel<string> (src, src.DatabaseTrackModel, ServiceManager.DbConnection,
Catalog.GetString ("All Genres ({0})"), src.UniqueId, BansheeQuery.GenreField, "Genre");
+ DatabaseYearListModel year_model = new DatabaseYearListModel (src, src.DatabaseTrackModel, ServiceManager.DbConnection, src.UniqueId);
if (this == src) {
this.artist_model = artist_model;
@@ -157,6 +158,7 @@ namespace Banshee.Sources
yield return genre_model;
yield return albumartist_model;
yield return artist_model;
+ yield return year_model;
yield return album_model;
}
diff --git a/src/Core/Banshee.Services/Makefile.am b/src/Core/Banshee.Services/Makefile.am
index ff63324..d952b31 100644
--- a/src/Core/Banshee.Services/Makefile.am
+++ b/src/Core/Banshee.Services/Makefile.am
@@ -20,6 +20,8 @@ SOURCES = \
Banshee.Collection.Database/DatabaseTrackListModel.cs \
Banshee.Collection.Database/DatabaseTrackModelCache.cs \
Banshee.Collection.Database/DatabaseTrackModelProvider.cs \
+ Banshee.Collection.Database/DatabaseYearInfo.cs \
+ Banshee.Collection.Database/DatabaseYearListModel.cs \
Banshee.Collection.Database/FilterModelProvider.cs \
Banshee.Collection.Database/IDatabaseTrackModelCache.cs \
Banshee.Collection.Database/IDatabaseTrackModelProvider.cs \
diff --git a/src/Core/Banshee.ThickClient/Banshee.Collection.Gui/YearListView.cs b/src/Core/Banshee.ThickClient/Banshee.Collection.Gui/YearListView.cs
new file mode 100644
index 0000000..b51e370
--- /dev/null
+++ b/src/Core/Banshee.ThickClient/Banshee.Collection.Gui/YearListView.cs
@@ -0,0 +1,49 @@
+//
+// YearListView.cs
+//
+// Author:
+// Frank Ziegler <funtastix googlemail com>
+//
+// 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;
+using Hyena.Data.Gui;
+
+using Banshee.Collection;
+using Banshee.ServiceStack;
+using Banshee.Gui;
+
+namespace Banshee.Collection.Gui
+{
+ public class YearListView : TrackFilterListView<YearInfo>
+ {
+ protected YearListView (IntPtr ptr) : base () {}
+
+ public YearListView () : base ()
+ {
+ column_controller.Add (new Column ("Year", new ColumnCellText ("Name", true), 1.0));
+ ColumnController = column_controller;
+ }
+
+ }
+}
diff --git a/src/Core/Banshee.ThickClient/Banshee.Sources.Gui/CompositeTrackSourceContents.cs b/src/Core/Banshee.ThickClient/Banshee.Sources.Gui/CompositeTrackSourceContents.cs
index 6e1fa85..2bb7a76 100644
--- a/src/Core/Banshee.ThickClient/Banshee.Sources.Gui/CompositeTrackSourceContents.cs
+++ b/src/Core/Banshee.ThickClient/Banshee.Sources.Gui/CompositeTrackSourceContents.cs
@@ -53,6 +53,7 @@ namespace Banshee.Sources.Gui
public class CompositeTrackSourceContents : FilteredListSourceContents, ITrackModelSourceContents
{
private QueryFilterView<string> genre_view;
+ private YearListView year_view;
private ArtistListView artist_view;
private ArtistListView albumartist_view;
private AlbumListView album_view;
@@ -71,6 +72,8 @@ namespace Banshee.Sources.Gui
<menuitem name=""AlbumArtist"" action=""AlbumArtistAction"" />
<separator />
<menuitem name=""Genre"" action=""GenreAction"" />
+ <separator />
+ <menuitem name=""Year"" action=""YearAction"" />
</menu>
<separator />
</placeholder>
@@ -108,6 +111,11 @@ namespace Banshee.Sources.Gui
Catalog.GetString ("Show Genre filter"), null,
Catalog.GetString ("Show a list of genres to filter by"), null, GenreListShown.Get ())});
+ configure_browser_actions.Add (new ToggleActionEntry [] {
+ new ToggleActionEntry ("YearAction", null,
+ Catalog.GetString ("Show Year filter"), null,
+ Catalog.GetString ("Show a list of years to filter by"), null, YearListShown.Get ())});
+
action_service.AddActionGroup (configure_browser_actions);
action_service.UIManager.AddUiFromString (menu_xml);
}
@@ -115,6 +123,7 @@ namespace Banshee.Sources.Gui
(action_service.FindAction("BrowserConfiguration.ArtistAction") as RadioAction).Changed += OnArtistFilterChanged;
//(action_service.FindAction("BrowserConfiguration.AlbumArtistAction") as RadioAction).Changed += OnArtistFilterChanged;
action_service.FindAction("BrowserConfiguration.GenreAction").Activated += OnGenreFilterChanged;;
+ action_service.FindAction("BrowserConfiguration.YearAction").Activated += OnYearFilterChanged;;
}
}
@@ -130,6 +139,18 @@ namespace Banshee.Sources.Gui
genre_view_widget.Parent.Visible = GenreListShown.Get ();
}
+ private void OnYearFilterChanged (object o, EventArgs args)
+ {
+ ToggleAction action = (ToggleAction)o;
+
+ ClearFilterSelections ();
+
+ YearListShown.Set (action.Active);
+
+ Widget year_view_widget = (Widget)year_view;
+ year_view_widget.Parent.Visible = YearListShown.Get ();
+ }
+
private void OnArtistFilterChanged (object o, ChangedArgs args)
{
Widget new_artist_view = args.Current.Value == 0 ? artist_view : albumartist_view;
@@ -187,6 +208,12 @@ namespace Banshee.Sources.Gui
artist_view = new ArtistListView ();
}
+ SetupFilterView (year_view = new YearListView ());
+ Widget year_view_widget = (Widget)year_view;
+ year_view_widget.Parent.Shown += delegate {
+ year_view_widget.Parent.Visible = YearListShown.Get ();
+ };
+
SetupFilterView (album_view = new AlbumListView ());
}
@@ -207,6 +234,10 @@ namespace Banshee.Sources.Gui
if (album_view.Model != null) {
album_view.Selection.Clear ();
}
+
+ if (year_view.Model != null) {
+ year_view.Selection.Clear ();
+ }
}
public void SetModels (TrackListModel track, IListModel<ArtistInfo> artist, IListModel<AlbumInfo> album, IListModel<QueryFilterInfo<string>> genre)
@@ -253,6 +284,8 @@ namespace Banshee.Sources.Gui
SetModel (track_view, track_source.TrackModel);
+ bool genre_view_model_set = false;
+
if (filterable_source != null && filterable_source.CurrentFilters != null) {
foreach (IListModel model in filterable_source.CurrentFilters) {
if (model is IListModel<ArtistInfo> && model is DatabaseArtistListModel)
@@ -261,8 +294,11 @@ namespace Banshee.Sources.Gui
SetModel (albumartist_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>>)
+ else if (model is IListModel<QueryFilterInfo<string>> && !genre_view_model_set) {
SetModel (genre_view, (model as IListModel<QueryFilterInfo<string>>));
+ genre_view_model_set = true;
+ } else if (model is DatabaseYearListModel)
+ SetModel (year_view, model as IListModel<YearInfo>);
// else
// Hyena.Log.DebugFormat ("CompositeTrackSourceContents got non-album/artist filter model: {0}", model);
}
@@ -279,6 +315,7 @@ namespace Banshee.Sources.Gui
SetModel (artist_view, null);
SetModel (albumartist_view, null);
SetModel (album_view, null);
+ SetModel (year_view, null);
SetModel (genre_view, null);
track_view.HeaderVisible = false;
}
@@ -298,5 +335,12 @@ namespace Banshee.Sources.Gui
"GenreListView Shown",
"Define if the GenreList filter view is shown or not"
);
+
+ public static readonly SchemaEntry<bool> YearListShown = new SchemaEntry<bool> (
+ "year_list_view", "shown",
+ false,
+ "YearListView Shown",
+ "Define if the YearList filter view is shown or not"
+ );
}
}
diff --git a/src/Core/Banshee.ThickClient/Banshee.ThickClient.csproj b/src/Core/Banshee.ThickClient/Banshee.ThickClient.csproj
index d23eb92..7df1fd9 100644
--- a/src/Core/Banshee.ThickClient/Banshee.ThickClient.csproj
+++ b/src/Core/Banshee.ThickClient/Banshee.ThickClient.csproj
@@ -306,6 +306,7 @@
<Compile Include="Banshee.CairoGlyphs\BansheeLineLogo.cs" />
<Compile Include="Banshee.Gui\IGlobalUIActions.cs" />
<Compile Include="Banshee.Gui\PlaybackSubtitleActions.cs" />
+ <Compile Include="Banshee.Collection.Gui\YearListView.cs" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<ProjectExtensions>
diff --git a/src/Core/Banshee.ThickClient/Makefile.am b/src/Core/Banshee.ThickClient/Makefile.am
index 5a3fdee..8e56ea8 100644
--- a/src/Core/Banshee.ThickClient/Makefile.am
+++ b/src/Core/Banshee.ThickClient/Makefile.am
@@ -34,6 +34,7 @@ SOURCES = \
Banshee.Collection.Gui/TrackFilterListView.cs \
Banshee.Collection.Gui/TrackListView.cs \
Banshee.Collection.Gui/XmlColumnController.cs \
+ Banshee.Collection.Gui/YearListView.cs \
Banshee.ContextPane/BaseContextPage.cs \
Banshee.ContextPane/ContextPageManager.cs \
Banshee.ContextPane/ContextPane.cs \
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]