banshee r3406 - in trunk/banshee: . src/Core/Banshee.Services/Banshee.Collection.Database src/Core/Banshee.Services/Banshee.Library src/Core/Banshee.Services/Banshee.Sources src/Core/Banshee.ThickClient/Banshee.Sources.Gui src/Extensions/Banshee.Lastfm/Banshee.Lastfm.Radio src/Libraries/Hyena.Gui/Hyena.Data.Gui/ListView src/Libraries/Hyena/Hyena.Collections



Author: gburt
Date: Tue Mar 11 00:15:32 2008
New Revision: 3406
URL: http://svn.gnome.org/viewvc/banshee?rev=3406&view=rev

Log:
2008-03-10  Gabriel Burt  <gabriel burt gmail com>

	* src/Core/Banshee.Services/Banshee.Collection.Database/TrackListDatabaseModel.cs:
	* src/Core/Banshee.Services/Banshee.Collection.Database/AlbumListDatabaseModel.cs:
	* src/Core/Banshee.Services/Banshee.Collection.Database/ArtistListDatabaseModel.cs:
	Add override to Reload method with options for suppressing notification
	and filtering.

	* src/Core/Banshee.Services/Banshee.Sources/DatabaseSource.cs: Remove
	RateLimitedFilter method, rework Reload to do suffice.  Remove cruft.
	Call track model's Reload with arguments to suppress notification and
	artist/album filtering.

	* src/Core/Banshee.Services/Banshee.Sources/PrimarySource.cs: Remove
	cruft, call PruneArtistsAlbums from within OnTracksDeleted

	* src/Core/Banshee.ThickClient/Banshee.Sources.Gui/CompositeTrackSourceContents.cs:
	Simplify Selection changed handler to just call Reload on the source.

	* src/Core/Banshee.ThickClient/Banshee.Sources.Gui/ISourceContents.cs:
	* src/Core/Banshee.ThickClient/Banshee.Sources.Gui/ObjectListSourceContents.cs:
	* src/Extensions/Banshee.Lastfm/Banshee.Lastfm.Radio/LastfmSourceContents.cs: 
	Change to use ISource instead of Source.

	* src/Libraries/Hyena.Gui/Hyena.Data.Gui/ListView/ListView_Interaction.cs:
	Prevent unnecessary Selection.Changed raising.

	* src/Libraries/Hyena/Hyena.Collections/Selection.cs: Add ToString
	override for debugging.

	* src/Core/Banshee.Services/Banshee.Library/LibraryImportManager.cs:
	Do ++count so Library gets refreshed on even 500s instead of N*500 + 1.


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.Library/LibraryImportManager.cs
   trunk/banshee/src/Core/Banshee.Services/Banshee.Sources/DatabaseSource.cs
   trunk/banshee/src/Core/Banshee.Services/Banshee.Sources/PrimarySource.cs
   trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Sources.Gui/CompositeTrackSourceContents.cs
   trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Sources.Gui/ISourceContents.cs
   trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Sources.Gui/ObjectListSourceContents.cs
   trunk/banshee/src/Extensions/Banshee.Lastfm/Banshee.Lastfm.Radio/LastfmSourceContents.cs
   trunk/banshee/src/Libraries/Hyena.Gui/Hyena.Data.Gui/ListView/ListView_Interaction.cs
   trunk/banshee/src/Libraries/Hyena/Hyena.Collections/Selection.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 Mar 11 00:15:32 2008
@@ -67,10 +67,16 @@
         private bool first_reload = true;
         public override void Reload ()
         {
+            Reload (false, true);
+        }
+
+        public void Reload (bool unfiltered, bool notify)
+        {
+            TrackListDatabaseModel track_model = unfiltered ? null : this.track_model;
+            ArtistListDatabaseModel artist_model = unfiltered ? null : this.artist_model;
+
             if (!first_reload || !cache.Warm) {
-                if (artist_model != null) {
-                    ArtistInfoFilter = artist_model.SelectedItems;
-                }
+                ArtistInfoFilter = artist_model == null ? null : artist_model.SelectedItems;
 
                 bool either = (artist_id_filter_query != null) || (track_model != null);
                 bool both = (artist_id_filter_query != null) && (track_model != null);
@@ -102,7 +108,10 @@
             first_reload = false;
             count = cache.Count + 1;
             select_all_album.Title = String.Format ("All Albums ({0})", count - 1);
-            OnReloaded ();
+
+            if (notify) {
+                OnReloaded ();
+            }
         }
         
         public override AlbumInfo this[int index] {

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 Mar 11 00:15:32 2008
@@ -62,36 +62,39 @@
         private bool first_reload = true;
         public override void Reload ()
         {
+            Reload (false, true);
+        }
+
+        public void Reload (bool unfiltered, bool notify)
+        {
+            TrackListDatabaseModel track_model = unfiltered ? null : this.track_model;
+
             if (!first_reload || !cache.Warm) {
                 reload_fragment = String.Format (
-                    @"FROM CoreArtists {0} ORDER BY Name",
-                    track_model != null ? String.Format(@"
+                    "FROM CoreArtists {0} ORDER BY Name",
+                    track_model == null ? null : String.Format (@"
                         WHERE CoreArtists.ArtistID IN
                             (SELECT CoreTracks.ArtistID FROM CoreTracks, CoreCache{1}
                                 WHERE CoreCache.ModelID = {0} AND
                                       CoreCache.ItemID = {2})",
-                        /*WHERE CoreArtists.ArtistID IN
-                            (SELECT CoreTracks.ArtistID FROM CoreTracks, CoreArtists, CoreCache
-                                WHERE CoreCache.ModelID = {0} AND
-                                      CoreCache.ItemID = CoreTracks.TrackID AND
-                                      CoreArtists.ArtistID = CoreTracks.ArtistID)",*/
                         track_model.CacheId,
                         track_model.CachesJoinTableEntries ? track_model.JoinFragment : null,
                         (!track_model.CachesJoinTableEntries)
                             ? "CoreTracks.TrackID"
                             : String.Format ("{0}.{1} AND CoreTracks.TrackID = {0}.{2}", track_model.JoinTable, track_model.JoinPrimaryKey, track_model.JoinColumn)
-                    ) : null
+                    )
                 );
 
-                //Console.WriteLine ("reload fragment for artists is {0}", reload_fragment);
-
                 cache.Reload ();
             }
 
             first_reload = false;
             count = cache.Count + 1;
             select_all_artist.Name = String.Format("All Artists ({0})", count - 1);
-            OnReloaded();
+
+            if (notify) {
+                OnReloaded();
+            }
         }
         
         public override ArtistInfo this[int index] {

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 Mar 11 00:15:32 2008
@@ -205,10 +205,10 @@
         private bool first_reload = true;
         public override void Reload ()
         {
-            Reload (true);
+            Reload (false, true);
         }
 
-        public void Reload (bool notify)
+        public void Reload (bool unfiltered, bool notify)
         {
             if (suppress_reload)
                 return;
@@ -220,22 +220,23 @@
             StringBuilder qb = new StringBuilder ();
             qb.Append (UnfilteredQuery);
 
+            ArtistListDatabaseModel artist_model = unfiltered ? null : this.artist_model;
+            AlbumListDatabaseModel album_model = unfiltered ? null : this.album_model;
+
             if (artist_model != null) {
                 ArtistInfoFilter = artist_model.SelectedItems;
             }
 
             if (album_model != null) {
-                //Console.WriteLine ("album_id_filter_query was {0}, and selection count = {1}", album_id_filter_query, album_model.Selection.Count);
                 AlbumInfoFilter = album_model.SelectedItems;
-                //Console.WriteLine ("album_id_filter_query now is {0}", album_id_filter_query);
             }
             
-            if (artist_id_filter_query != null) {
+            if (!unfiltered && artist_id_filter_query != null) {
                 qb.Append ("AND ");
                 qb.Append (artist_id_filter_query);
             }
                     
-            if (album_id_filter_query != null) {
+            if (!unfiltered && album_id_filter_query != null) {
                 qb.Append ("AND ");
                 qb.Append (album_id_filter_query);
             }
@@ -264,6 +265,11 @@
             }
         }
 
+        internal void NotifyReloaded ()
+        {
+            OnReloaded ();
+        }
+
         public override int IndexOf (TrackInfo track)
         {
             DatabaseTrackInfo db_track = track as DatabaseTrackInfo;

Modified: trunk/banshee/src/Core/Banshee.Services/Banshee.Library/LibraryImportManager.cs
==============================================================================
--- trunk/banshee/src/Core/Banshee.Services/Banshee.Library/LibraryImportManager.cs	(original)
+++ trunk/banshee/src/Core/Banshee.Services/Banshee.Library/LibraryImportManager.cs	Tue Mar 11 00:15:32 2008
@@ -148,7 +148,7 @@
                 throw;
             }
 
-            if (count++ % 500 == 0) {
+            if (++count % 500 == 0) {
                 ServiceManager.SourceManager.Library.NotifyTracksAdded ();
             }
             

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 Mar 11 00:15:32 2008
@@ -54,7 +54,6 @@
         protected ArtistListDatabaseModel artist_model;
 
         protected RateLimiter reload_limiter;
-        protected RateLimiter filter_limiter;
         
         public DatabaseSource (string generic_name, string name, string id, int order) : base (generic_name, name, order)
         {
@@ -63,7 +62,6 @@
             artist_model = new ArtistListDatabaseModel (track_model, ServiceManager.DbConnection, uuid);
             album_model = new AlbumListDatabaseModel (track_model, artist_model, ServiceManager.DbConnection, uuid);
             reload_limiter = new RateLimiter (RateLimitedReload);
-            filter_limiter = new RateLimiter (RateLimitedFilter);
         }
 
 #region Public Properties
@@ -95,7 +93,8 @@
         public override string FilterQuery {
             set {
                 base.FilterQuery = value;
-                filter_limiter.Execute ();
+                track_model.Filter = FilterQuery;
+                reload_limiter.Execute ();
             }
         }
 
@@ -143,60 +142,36 @@
         protected virtual void RateLimitedReload ()
         {
             lock (track_model) {
-                ReloadTrackModel ();
+                // First, reload the track model w/o the artist/album filter
+                ReloadTrackModel (true, false);
+
+                // Then, reload the artist/album models
                 artist_model.Reload ();
                 album_model.Reload ();
+
+                // Then, reload the track model with the artist/album filters, if any
+                if (!artist_model.Selection.AllSelected || !album_model.Selection.AllSelected) {
+                    ReloadTrackModel ();
+                } else {
+                    track_model.NotifyReloaded ();
+                }
+
                 OnUpdated ();
             }
         }
 
         protected virtual void ReloadTrackModel ()
         {
-            ReloadTrackModel (true);
+            ReloadTrackModel (false, true);
         }
 
-        protected void ReloadTrackModel (bool notify)
+        protected void ReloadTrackModel (bool unfiltered, bool notify)
         {
-            track_model.Reload (notify);
+            track_model.Reload (unfiltered, notify);
             Hyena.Log.DebugFormat ("Called {0}::ReloadTrackModel ({1}) [Count={2}]", GetType ().FullName, 
                 notify, track_model.Count);
         }
 
-        protected virtual void RateLimitedFilter ()
-        {
-            lock (this) {
-                // First, reload the track model w/o the artist/album filter
-                track_model.SuppressReloads = true;
-                track_model.Filter = FilterQuery;
-                track_model.ClearArtistAlbumFilters ();
-                track_model.SuppressReloads = false;
-                ReloadTrackModel (false);
-
-                // Then, reload the artist/album models
-                artist_model.Reload ();
-                album_model.Reload ();
-
-                // Then, reload the track model with the artist/album filters
-                track_model.SuppressReloads = true;
-                track_model.ArtistInfoFilter = artist_model.SelectedItems;
-                track_model.AlbumInfoFilter = album_model.SelectedItems;
-                track_model.SuppressReloads = false;
-                ReloadTrackModel ();
-
-                OnUpdated ();
-            }
-        }
-
-        /*protected virtual void ReloadChildren ()
-        {
-            foreach (Source child in Children) {
-                ITrackModelSource c = child as ITrackModelSource;
-                if (c != null && !c.HasDependencies) {
-                    c.Reload ();
-                }
-            }
-        }*/
-        
         public virtual bool HasDependencies {
             get { return false; }
         }
@@ -233,7 +208,6 @@
         public virtual void DeleteSelectedTracks (TrackListDatabaseModel model)
         {
             WithTrackSelection (model, DeleteTrackRange);
-            PruneArtistsAlbums ();
             OnTracksDeleted ();
         }
 
@@ -283,6 +257,7 @@
 
         protected virtual void OnTracksDeleted ()
         {
+            PruneArtistsAlbums ();
             HandleTracksDeleted (this, new TrackEventArgs ());
             foreach (PrimarySource psource in PrimarySources) {
                 psource.NotifyTracksDeleted ();
@@ -392,12 +367,8 @@
 
         protected virtual void PruneArtistsAlbums ()
         {
-            //Hyena.Log.Information ("Pruning artists/albums");
-            ServiceManager.DbConnection.Execute (PruneCommand);
-            //Hyena.Log.Information ("Clearing artists/albums cache");
-            artist_model.Reload ();
-            album_model.Reload ();
-            //Hyena.Log.Information ("Done clearing artists/albums cache");
+            //Console.WriteLine ("Pruning with {0}", PruneCommand.Text);
+            //ServiceManager.DbConnection.Execute (PruneCommand);
         }
 
         protected virtual void HandleTracksAdded (Source sender, TrackEventArgs args)

Modified: trunk/banshee/src/Core/Banshee.Services/Banshee.Sources/PrimarySource.cs
==============================================================================
--- trunk/banshee/src/Core/Banshee.Services/Banshee.Sources/PrimarySource.cs	(original)
+++ trunk/banshee/src/Core/Banshee.Services/Banshee.Sources/PrimarySource.cs	Tue Mar 11 00:15:32 2008
@@ -147,32 +147,6 @@
             }
         }
 
-        /*public override void RemoveTracks (IEnumerable<TrackInfo> tracks)
-        {
-
-            // BEGIN transaction
-
-            int i = 0;
-            DatabaseTrackInfo ltrack;
-            foreach (TrackInfo track in tracks) {
-                ltrack = track as DatabaseTrackInfo;
-                if (ltrack == null)
-                    continue;
-
-                command.ApplyValues (ltrack.DbId, ltrack.DbId, ltrack.DbId);
-                ServiceManager.DbConnection.Execute (command);
-
-                if (++i % 100 == 0) {
-                    // COMMIT and BEGIN new transaction
-                }
-            }
-
-            // COMMIT transaction
-
-            // Reload the library, all playlists, etc
-            Reload ();
-        }*/
-
         public override void SetParentSource (Source source)
         {
             if (source is PrimarySource) {
@@ -209,6 +183,7 @@
         protected override void OnTracksDeleted ()
         {
             ThreadAssist.SpawnFromMain (delegate {
+                PruneArtistsAlbums ();
                 Reload ();
 
                 TrackEventHandler handler = TracksDeleted;
@@ -220,14 +195,6 @@
 
         protected override void OnTracksRemoved ()
         {
-            PruneArtistsAlbums ();
-            OnTracksDeleted ();
-        }
-
-        public override void RemoveSelectedTracks (TrackListDatabaseModel model)
-        {
-            base.RemoveSelectedTracks (model);
-            PruneArtistsAlbums ();
             OnTracksDeleted ();
         }
 

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	Tue Mar 11 00:15:32 2008
@@ -267,45 +267,22 @@
 
             if (selection.AllSelected) {
                 if (model != null && o == artist_view.Selection ) {
-                    model.ClearArtistAlbumFilters ();
-                    album_model.ArtistInfoFilter = null;
-                    album_model.Reload ();
-                    if (!album_model.Selection.AllSelected) {
-                        UpdateAlbumSelectionFilters ();
-                    }
+                    track_source.Reload ();
                     artist_view.ScrollTo (0);
                 } else if (model != null && o == album_view.Selection) {
-                    model.AlbumInfoFilter = null;
-                    model.Reload ();
+                    track_source.Reload ();
                     album_view.ScrollTo (0);
                 }
                 return;
             }
             
             if (o == artist_view.Selection) {
-                ArtistInfo [] artists = new ArtistInfo[selection.Count];
-                int i = 0;
-            
-                foreach(int row_index in artist_view.Selection) {
-                    artists[i++] = artist_view.Model[row_index];
-                }
-            
-                model.AlbumInfoFilter = null;
-                model.ArtistInfoFilter = artists;
-                model.Reload ();
-                album_model.ArtistInfoFilter = artists;
-                album_model.Reload ();
+                track_source.Reload ();
             } else if (o == album_view.Selection) {
-                UpdateAlbumSelectionFilters ();
+                track_source.Reload ();
             }
         }
 
-        private void UpdateAlbumSelectionFilters ()
-        {
-            (track_view.Model as TrackListModel).AlbumInfoFilter = (album_view.Model as AlbumListModel).SelectedItems;
-            track_view.Model.Reload ();
-        }
-        
         public void SetModels (TrackListModel track, ArtistListModel artist, AlbumListModel album)
         {
             // Save the old vertical positions
@@ -388,16 +365,15 @@
 
 #region Implement ISourceContents
 
-        private Source source;
+        private ITrackModelSource track_source;
 
-        public bool SetSource (Source source)
+        public bool SetSource (ISource source)
         {
-            ITrackModelSource track_source = source as ITrackModelSource;
+            track_source = source as ITrackModelSource;
             if (track_source == null) {
                 return false;
             }
 
-            this.source = source;
             SetModels (track_source.TrackModel, track_source.ArtistModel, track_source.AlbumModel);
             TrackView.HeaderVisible = true;
             return true;
@@ -405,13 +381,13 @@
 
         public void ResetSource ()
         {
-            source = null;
+            track_source = null;
             SetModels (null, null, null);
             TrackView.HeaderVisible = false;
         }
 
-        public Source Source {
-            get { return source; }
+        public ISource Source {
+            get { return track_source; }
         }
 
         public Widget Widget {

Modified: trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Sources.Gui/ISourceContents.cs
==============================================================================
--- trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Sources.Gui/ISourceContents.cs	(original)
+++ trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Sources.Gui/ISourceContents.cs	Tue Mar 11 00:15:32 2008
@@ -36,9 +36,9 @@
 {
     public interface ISourceContents
     {
-        bool SetSource (Source source);
+        bool SetSource (ISource source);
         void ResetSource ();
-        Source Source { get; }
+        ISource Source { get; }
         Widget Widget { get; }
     }
 }

Modified: trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Sources.Gui/ObjectListSourceContents.cs
==============================================================================
--- trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Sources.Gui/ObjectListSourceContents.cs	(original)
+++ trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Sources.Gui/ObjectListSourceContents.cs	Tue Mar 11 00:15:32 2008
@@ -48,7 +48,7 @@
     public class ObjectListSourceContents : ScrolledWindow, ISourceContents
     {
         private ObjectListView object_view;
-        private Source source;
+        private ISource source;
 
         public ObjectListSourceContents () : base ()
         {
@@ -63,14 +63,14 @@
             object_view.SetModel (null);
         }
 
-        public bool SetSource (Source source)
+        public bool SetSource (ISource source)
         {
             object_view.SetModel((Hyena.Data.IObjectListModel)source);
             this.source = source;
             return true;
         }
 
-        public Source Source {
+        public ISource Source {
             get { return source; }
         }
 

Modified: trunk/banshee/src/Extensions/Banshee.Lastfm/Banshee.Lastfm.Radio/LastfmSourceContents.cs
==============================================================================
--- trunk/banshee/src/Extensions/Banshee.Lastfm/Banshee.Lastfm.Radio/LastfmSourceContents.cs	(original)
+++ trunk/banshee/src/Extensions/Banshee.Lastfm/Banshee.Lastfm.Radio/LastfmSourceContents.cs	Tue Mar 11 00:15:32 2008
@@ -37,7 +37,7 @@
         {
         }
 
-        public bool SetSource (Source src)
+        public bool SetSource (ISource src)
         {
             lastfm = src as LastfmSource;
             if (lastfm == null) {
@@ -53,7 +53,7 @@
             return true;
         }
 
-        public Source Source {
+        public ISource Source {
             get { return lastfm; }
         }
 

Modified: trunk/banshee/src/Libraries/Hyena.Gui/Hyena.Data.Gui/ListView/ListView_Interaction.cs
==============================================================================
--- trunk/banshee/src/Libraries/Hyena.Gui/Hyena.Data.Gui/ListView/ListView_Interaction.cs	(original)
+++ trunk/banshee/src/Libraries/Hyena.Gui/Hyena.Data.Gui/ListView/ListView_Interaction.cs	Tue Mar 11 00:15:32 2008
@@ -334,7 +334,7 @@
                     return true;
                 }
                 
-                if (Selection.Contains (row_index)) {
+                if (Selection.Contains (row_index) && Selection.Count > 1) {
                     Selection.Clear (false);
                     Selection.Select (row_index);
                     FocusRow (row_index);

Modified: trunk/banshee/src/Libraries/Hyena/Hyena.Collections/Selection.cs
==============================================================================
--- trunk/banshee/src/Libraries/Hyena/Hyena.Collections/Selection.cs	(original)
+++ trunk/banshee/src/Libraries/Hyena/Hyena.Collections/Selection.cs	Tue Mar 11 00:15:32 2008
@@ -197,5 +197,16 @@
             return ranges.GetEnumerator ();
         }
 #endif
+
+        public override string ToString ()
+        {
+            System.Text.StringBuilder sb = new System.Text.StringBuilder ();
+            sb.AppendFormat ("<Selection Count={0}", Count);
+            foreach (RangeCollection.Range range in Ranges) {
+                sb.AppendFormat (" ({0}, {1})", range.Start, range.End);
+            }
+            sb.Append (">");
+            return sb.ToString ();
+        }
     }
 }



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