[f-spot/mipmapped-loading: 10/12] Load IconView thumbnails through the Loaders.



commit 9e9935bec69bec075eec7f0980bf70c217e74793
Author: Ruben Vermeersch <ruben savanne be>
Date:   Sun Jun 20 18:43:39 2010 +0200

    Load IconView thumbnails through the Loaders.

 src/Import/ImportController.cs |   13 ++-
 src/MainWindow.cs              |    6 +-
 src/Makefile.am                |    1 -
 src/PixbufCache.cs             |  388 ----------------------------------------
 src/SingleView.cs              |    2 -
 src/ThumbnailCommand.cs        |   14 ++-
 src/Widgets/Filmstrip.cs       |    4 +-
 src/Widgets/IconView.cs        |  113 ++++++------
 src/Widgets/ImageView.cs       |    2 +
 9 files changed, 87 insertions(+), 456 deletions(-)
---
diff --git a/src/Import/ImportController.cs b/src/Import/ImportController.cs
index f5f344a..471a6fb 100644
--- a/src/Import/ImportController.cs
+++ b/src/Import/ImportController.cs
@@ -1,5 +1,6 @@
 using Hyena;
 using FSpot.Utils;
+using FSpot.Tasks;
 using System;
 using System.Collections.Generic;
 using System.Threading;
@@ -330,11 +331,21 @@ namespace FSpot.Import
             }
 
             // Prepare thumbnail (Import is I/O bound anyway)
-            ThumbnailLoader.Default.Request (destination, ThumbnailSize.Large, 10);
+            GenerateThumbnail (photo);
 
             imported_photos.Add (photo.Id);
         }
 
+        void GenerateThumbnail (IBrowsableItem photo)
+        {
+            var loader = App.Instance.Loaders.RequestLoader (photo.DefaultVersion);
+            var preview_task = loader.FindBestPreview (256, 256);
+            var task = new WorkerThreadTask<bool> (() => { preview_task.Result.Dispose (); return false; }) {
+                Priority = TaskPriority.Background
+            };
+            preview_task.ContinueWith (task);
+        }
+
         SafeUri FindImportDestination (IBrowsableItem item)
         {
             var uri = item.DefaultVersion.Uri;
diff --git a/src/MainWindow.cs b/src/MainWindow.cs
index 29b1f77..868c52c 100644
--- a/src/MainWindow.cs
+++ b/src/MainWindow.cs
@@ -1046,16 +1046,16 @@ namespace FSpot
 	
 				bool use_icon = false;;
 				while (len-- > 0) {
-					FSpot.PixbufCache.CacheEntry entry = icon_view.Cache.Lookup (photos [len].DefaultVersion.Uri);
+					var entry = icon_view.Cache.Get (photos [len].DefaultVersion.Uri);
 	
 					Pixbuf thumbnail = null;
 					if (entry != null) {
 						Cms.Profile screen_profile;
 						if (FSpot.ColorManagement.Profiles.TryGetValue (Preferences.Get<string> (Preferences.COLOR_MANAGEMENT_DISPLAY_PROFILE), out screen_profile)) {
-							thumbnail = entry.Pixbuf.Copy ();
+							thumbnail = entry.Copy ();
 							FSpot.ColorManagement.ApplyProfile (thumbnail, screen_profile);
 						} else
-							thumbnail = entry.ShallowCopyPixbuf ();
+							thumbnail = entry.ShallowCopy ();
 					}
 					
 					if (thumbnail != null) {
diff --git a/src/Makefile.am b/src/Makefile.am
index a5c2a14..ca37638 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -123,7 +123,6 @@ SOURCES = \
 	PhotoVersionMenu.cs \
 	PhotoView.cs \
 	PixbufUtils.cs \
-	PixbufCache.cs \
 	Preferences.cs  \
 	PrintOperation.cs \
 	ProgressItem.cs \
diff --git a/src/SingleView.cs b/src/SingleView.cs
index ccc9b4a..89b7df3 100644
--- a/src/SingleView.cs
+++ b/src/SingleView.cs
@@ -125,8 +125,6 @@ namespace FSpot {
 			sidebar.CloseRequested += HandleHideSidePane;
 			sidebar.Show ();
 
-			ThumbnailLoader.Default.OnPixbufLoaded += delegate { directory_view.QueueDraw (); };
-
 			image_view = new PhotoImageView (collection);
 			GtkUtil.ModifyColors (image_view);
 			GtkUtil.ModifyColors (image_scrolled);
diff --git a/src/ThumbnailCommand.cs b/src/ThumbnailCommand.cs
index 34a9756..95f0bfc 100644
--- a/src/ThumbnailCommand.cs
+++ b/src/ThumbnailCommand.cs
@@ -2,6 +2,7 @@ using System;
 using Gtk;
 using FSpot;
 using FSpot.Utils;
+using FSpot.Tasks;
 using FSpot.UI.Dialog;
 
 public class ThumbnailCommand {
@@ -16,7 +17,6 @@ public class ThumbnailCommand {
 	public bool Execute (Photo [] photos)
 	{
 		ProgressDialog progress_dialog = null;
-        var loader = ThumbnailLoader.Default;
 		if (photos.Length > 1) {
 			progress_dialog = new ProgressDialog (Mono.Unix.Catalog.GetString ("Updating Thumbnails"),
 							      ProgressDialog.CancelButtonType.Stop,
@@ -30,7 +30,7 @@ public class ThumbnailCommand {
 				break;
 
 			foreach (uint version_id in p.VersionIds) {
-				loader.Request (p.VersionUri (version_id), ThumbnailSize.Large, 10);
+                GenerateThumbnail (p.GetVersion (version_id));
 			}
 			
 			count++;
@@ -41,4 +41,14 @@ public class ThumbnailCommand {
 
 		return true;
 	}
+
+    void GenerateThumbnail (ILoadable item)
+    {
+        var loader = App.Instance.Loaders.RequestLoader (item);
+        var preview_task = loader.FindBestPreview (256, 256);
+        var task = new WorkerThreadTask<bool> (() => { preview_task.Result.Dispose (); return false; }) {
+            Priority = TaskPriority.Background
+        };
+        preview_task.ContinueWith (task);
+    }
 }
diff --git a/src/Widgets/Filmstrip.cs b/src/Widgets/Filmstrip.cs
index 939026b..97ec661 100644
--- a/src/Widgets/Filmstrip.cs
+++ b/src/Widgets/Filmstrip.cs
@@ -611,9 +611,9 @@ namespace FSpot.Widgets
 				var task = new WorkerThreadTask<bool> (() => {
 					Pixbuf pixbuf = preview_task.Result;
 					if (SquaredThumbs) {
-					current = PixbufUtils.IconFromPixbuf (pixbuf, ThumbSize);
+						current = PixbufUtils.IconFromPixbuf (pixbuf, ThumbSize);
 					} else {
-					current = pixbuf.ScaleSimple (ThumbSize, ThumbSize, InterpType.Bilinear);
+						current = pixbuf.ScaleSimple (ThumbSize, ThumbSize, InterpType.Bilinear);
 					}
 					pixbuf.Dispose ();
 
diff --git a/src/Widgets/IconView.cs b/src/Widgets/IconView.cs
index fa92e69..c590d3b 100644
--- a/src/Widgets/IconView.cs
+++ b/src/Widgets/IconView.cs
@@ -17,6 +17,9 @@ using System.Collections;
 using System.IO;
 using FSpot.Utils;
 using FSpot.Platform;
+using FSpot.Utils;
+using FSpot.Tasks;
+using Hyena;
 
 namespace FSpot.Widgets
 {
@@ -32,8 +35,14 @@ namespace FSpot.Widgets
 
 	public class IconView : Gtk.Layout {
 
-		// Public properties.
-		FSpot.PixbufCache cache;
+		DisposableCache<SafeUri, Pixbuf> pixbuf_cache;
+
+		public DisposableCache<SafeUri, Pixbuf> Cache {
+			get {
+				return pixbuf_cache;
+			}
+		}
+
 
 		/* preserve the scroll postion when possible */
 		private bool scroll;
@@ -93,12 +102,6 @@ namespace FSpot.Widgets
 			}
 		}
 
-		public FSpot.PixbufCache Cache {
-			get {
-				return cache;
-			}
-		}
-
 		private bool display_tags = true;
 		public bool DisplayTags {
 			get {
@@ -214,8 +217,7 @@ namespace FSpot.Widgets
 
 		protected IconView () : base (null, null)
 		{
-			cache = new FSpot.PixbufCache ();
-			cache.OnPixbufLoaded += HandlePixbufLoaded;
+			pixbuf_cache = new DisposableCache<SafeUri, Pixbuf> (100);
 
 			ScrollAdjustmentsSet += new ScrollAdjustmentsSetHandler (HandleScrollAdjustmentsSet);
 
@@ -635,7 +637,7 @@ namespace FSpot.Widgets
 		public void UpdateThumbnail (int thumbnail_num)
 		{
 			FSpot.IBrowsableItem photo = collection [thumbnail_num];
-			cache.Remove (photo.DefaultVersion.Uri);
+			pixbuf_cache.Remove (photo.DefaultVersion.Uri);
 			InvalidateCell (thumbnail_num);
 		}
 
@@ -839,6 +841,25 @@ namespace FSpot.Widgets
 		// rectangle of dragging selection
 		private Rectangle rect_select;
 
+		void LoadThumbnail (IBrowsableItem item, int thumbnail_num)
+		{
+			var loader = App.Instance.Loaders.RequestLoader (item.DefaultVersion);
+			var preview_task = loader.FindBestPreview (ThumbnailWidth, ThumbnailHeight);
+			var task = new WorkerThreadTask<bool> (() => {
+				if (preview_task.Result == null)
+					return false;
+				ThreadAssist.ProxyToMain (() => {
+					using (var pixbuf = preview_task.Result) {
+						HandlePixbufLoaded (pixbuf.ShallowCopy (), thumbnail_num, item.DefaultVersion.Uri);
+					}
+				});
+				return false;
+			}) {
+				Priority = TaskPriority.Interactive
+			};
+			preview_task.ContinueWith (task);
+		}
+
 		System.Collections.Hashtable date_layouts = new Hashtable ();
 		// FIXME Cache the GCs?
 		private void DrawCell (int thumbnail_num, Gdk.Rectangle area)
@@ -850,11 +871,9 @@ namespace FSpot.Widgets
 
 			FSpot.IBrowsableItem photo = collection [thumbnail_num];
 
-			FSpot.PixbufCache.CacheEntry entry = cache.Lookup (photo.DefaultVersion.Uri);
+			var entry = pixbuf_cache.Get (photo.DefaultVersion.Uri);
 			if (entry == null)
-				cache.Request (photo.DefaultVersion.Uri, thumbnail_num, ThumbnailWidth, ThumbnailHeight);
-			else
-				entry.Data = thumbnail_num;
+				LoadThumbnail (photo, thumbnail_num);
 
 			bool selected = selection.Contains (thumbnail_num);
 			StateType cell_state = selected ? (HasFocus ? StateType.Selected : StateType.Active) : State;
@@ -881,7 +900,7 @@ namespace FSpot.Widgets
 
 			Gdk.Pixbuf thumbnail = null;
 			if (entry != null)
-				thumbnail = entry.ShallowCopyPixbuf ();
+				thumbnail = entry.ShallowCopy ();
 
 			Gdk.Rectangle draw = Gdk.Rectangle.Zero;
 			if (Gdk.Rectangle.Inflate (image_bounds, expansion + 1, expansion + 1).Intersect (area, out image_bounds) && thumbnail != null) {
@@ -893,8 +912,10 @@ namespace FSpot.Widgets
 				region.Y = (int) bounds.Y + ThumbnailHeight - region.Height + cell_border_width;
 
 				if (Math.Abs (region.Width - thumbnail.Width) > 1
-					&& Math.Abs (region.Height - thumbnail.Height) > 1)
-				cache.Reload (entry, thumbnail_num, thumbnail.Width, thumbnail.Height);
+					&& Math.Abs (region.Height - thumbnail.Height) > 1) {
+					pixbuf_cache.Remove (photo.DefaultVersion.Uri);
+					LoadThumbnail (photo, thumbnail_num);
+				}
 
 				region = Gdk.Rectangle.Inflate (region, expansion, expansion);
 				Pixbuf temp_thumbnail;
@@ -910,14 +931,6 @@ namespace FSpot.Widgets
 						*/
 						temp_thumbnail = thumbnail.ScaleSimple (region.Width, region.Height,
 								InterpType.Bilinear);
-
-
-						lock (entry) {
-							if (entry.Reload && expansion == 0 && !entry.IsDisposed) {
-								entry.SetPixbufExtended (temp_thumbnail.ShallowCopy (), false);
-								entry.Reload = true;
-							}
-						}
 					} else {
 						temp_thumbnail = thumbnail.ScaleSimple (region.Width, region.Height,
 								InterpType.Bilinear);
@@ -1250,7 +1263,6 @@ namespace FSpot.Widgets
 			int i;
 
 			FSpot.IBrowsableItem photo;
-			FSpot.PixbufCache.CacheEntry entry;
 
 			// Preload the cache with images aroud the expose area
 			// FIXME the preload need to be tuned to the Cache size but this is a resonable start
@@ -1272,17 +1284,11 @@ namespace FSpot.Widgets
 				int cell = back ? ecell - i - 1 : scell + mid + i;
 
 				photo = collection [cell];
-
-				entry = cache.Lookup (photo.DefaultVersion.Uri);
-				if (entry == null)
-					cache.Request (photo.DefaultVersion.Uri, cell, ThumbnailWidth, ThumbnailHeight);
+				LoadThumbnail (photo, cell);
 
 				cell = back ? scell + i : scell + mid - i - 1;
 				photo = collection [cell];
-
-				entry = cache.Lookup (photo.DefaultVersion.Uri);
-				if (entry == null)
-					cache.Request (photo.DefaultVersion.Uri, cell, ThumbnailWidth, ThumbnailHeight);
+				LoadThumbnail (photo, cell);
 			}
 		}
 
@@ -1368,40 +1374,34 @@ namespace FSpot.Widgets
 			Scroll ();
 		}
 
-		private void HandlePixbufLoaded (FSpot.PixbufCache cache, FSpot.PixbufCache.CacheEntry entry)
+		private void HandlePixbufLoaded (Pixbuf pixbuf, int thumbnail_num, SafeUri uri)
 		{
-			Gdk.Pixbuf result = entry.ShallowCopyPixbuf ();
-			int order = (int) entry.Data;
-
-			if (result == null)
-				return;
-
 			// We have to do the scaling here rather than on load because we need to preserve the
 			// Pixbuf option iformation to verify the thumbnail validity later
 			int width, height;
-			PixbufUtils.Fit (result, ThumbnailWidth, ThumbnailHeight, false, out width, out height);
-			if (result.Width > width && result.Height > height) {
+			PixbufUtils.Fit (pixbuf, ThumbnailWidth, ThumbnailHeight, false, out width, out height);
+			if (pixbuf.Width > width && pixbuf.Height > height) {
 				//  Log.Debug ("scaling");
-				Gdk.Pixbuf temp = PixbufUtils.ScaleDown (result, width, height);
-				result.Dispose ();
-				result = temp;
-			} else if (result.Width < ThumbnailWidth && result.Height < ThumbnailHeight) {
+				Gdk.Pixbuf temp = PixbufUtils.ScaleDown (pixbuf, width, height);
+				pixbuf.Dispose ();
+				pixbuf = temp;
+			} else if (pixbuf.Width < ThumbnailWidth && pixbuf.Height < ThumbnailHeight) {
 				// FIXME this is a workaround to handle images whose actual size is smaller than
 				// the thumbnail size, it needs to be fixed at a different level.
 				Gdk.Pixbuf temp = new Gdk.Pixbuf (Gdk.Colorspace.Rgb, true, 8, ThumbnailWidth, ThumbnailHeight);
 				temp.Fill (0x00000000);
-				result.CopyArea (0, 0,
-						result.Width, result.Height,
+				pixbuf.CopyArea (0, 0,
+						pixbuf.Width, pixbuf.Height,
 						temp,
-						(temp.Width - result.Width)/ 2,
-						temp.Height - result.Height);
+						(temp.Width - pixbuf.Width)/ 2,
+						temp.Height - pixbuf.Height);
 
-				result.Dispose ();
-				result = temp;
+				pixbuf.Dispose ();
+				pixbuf = temp;
 			}
 
-			cache.Update (entry, result);
-			InvalidateCell (order);
+			pixbuf_cache.Add (uri, pixbuf);
+			InvalidateCell (thumbnail_num);
 		}
 
 		public Gdk.Rectangle CellBounds (int cell)
@@ -1828,7 +1828,6 @@ namespace FSpot.Widgets
 
 		private void HandleDestroyed (object sender, System.EventArgs args)
 		{
-			cache.OnPixbufLoaded -= HandlePixbufLoaded;
 			CancelThrob ();
 		}
 	}
diff --git a/src/Widgets/ImageView.cs b/src/Widgets/ImageView.cs
index 8796ee9..4cae1e9 100644
--- a/src/Widgets/ImageView.cs
+++ b/src/Widgets/ImageView.cs
@@ -337,6 +337,8 @@ namespace FSpot.Widgets
 
 		protected override void ForAll (bool include_internals, Gtk.Callback callback)
 		{
+			if (children == null)
+				return;
 			foreach (var child in children) 
 				callback (child.Widget);
 		}



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