[mistelix] Gnome-desktop thumbnailing infrastructure for loading and storing thumbnails when it is available



commit 3cefeaacd8cfa7cbb8c0702b294ee189d6ecbc7c
Author: Jordi Mas <jmas softcatala org>
Date:   Thu Jul 30 10:50:23 2009 +0200

    Gnome-desktop thumbnailing infrastructure for loading and storing thumbnails when it is available

 Test/perf/Makefile                       |   26 ++--
 Test/perf/SlideImagePerf.cs              |   24 ++++
 Test/perf/ThumbnailCachePerf.cs          |   76 +++++++++++++
 src/Backends/ThumbnailCache/Factory.cs   |   59 ++++++++++
 src/Backends/ThumbnailCache/Gnome.cs     |  180 ++++++++++++++++++++++++++++++
 src/Backends/ThumbnailCache/None.cs      |   56 +++++++++
 src/Backends/ThumbnailCache/Provider.cs  |   42 +++++++
 src/Core/ThumbnailSizeManager.cs         |    1 +
 src/DataModel/SlideShowProjectElement.cs |    8 +-
 src/Makefile.am                          |    6 +-
 src/Widgets/FileView.cs                  |   26 +++--
 src/Widgets/ImagesFileView.cs            |    6 +-
 12 files changed, 484 insertions(+), 26 deletions(-)
---
diff --git a/Test/perf/Makefile b/Test/perf/Makefile
index b57745b..948febe 100644
--- a/Test/perf/Makefile
+++ b/Test/perf/Makefile
@@ -1,19 +1,19 @@
-all: outfile
+SLIDEIMAGEPERF = SlideImagePerf.exe
+THUMBNAILCACHEPERF = ThumbnailCachePerf.exe
 
-outfile = slideimage.exe
-
-SOURCES = SlideImagePerf.cs
-	  
+all: $(SLIDEIMAGEPERF) $(THUMBNAILCACHEPERF)
 	
-PKGS = 					\
-	-pkg:gtk-sharp-2.0 -pkg:mono-addins
+PKGS = -pkg:gtk-sharp-2.0 -pkg:mono-addins -pkg:mistelix
 
-REFS =					\
-	-r:../../src/mistelix.exe
+REFS =
 
 
-outfile: $(SOURCES) 
-	gmcs $(PKGS) $(REFS) $(SOURCES) $(RESOURCES) -out:$(outfile)	
+SlideImagePerf.exe: SlideImagePerf.cs
+	gmcs $(PKGS) $(REFS) $(RESOURCES)  SlideImagePerf.cs -out:$(SLIDEIMAGEPERF)
+ 
+ThumbnailCachePerf.exe: ThumbnailCachePerf.cs
+	gmcs $(PKGS) $(REFS) $(RESOURCES) ThumbnailCachePerf.cs -out:$(THUMBNAILCACHEPERF)
 
-clean:
-	rm -f *~ *.dll TestResult.xml *.db
+clean: 
+	rm -f $(SLIDEIMAGEPERF) $(SLIDEIMAGEPERF).mdb
+	rm -f $(THUMBNAILCACHEPERF) $(THUMBNAILCACHEPERF).mdb
diff --git a/Test/perf/SlideImagePerf.cs b/Test/perf/SlideImagePerf.cs
index 1231d2b..b3c1637 100644
--- a/Test/perf/SlideImagePerf.cs
+++ b/Test/perf/SlideImagePerf.cs
@@ -1,3 +1,27 @@
+//
+// Copyright (C) 2009 Jordi Mas i Hernandez, jmas softcatala org
+//
+// 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 Gtk;
 using System.Diagnostics;
diff --git a/Test/perf/ThumbnailCachePerf.cs b/Test/perf/ThumbnailCachePerf.cs
new file mode 100644
index 0000000..76fc9f1
--- /dev/null
+++ b/Test/perf/ThumbnailCachePerf.cs
@@ -0,0 +1,76 @@
+//
+// Copyright (C) 2009 Jordi Mas i Hernandez, jmas softcatala org
+//
+// 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.IO;
+using Gdk;
+using System.Diagnostics;
+using Mistelix.Core;
+using Mistelix.DataModel;
+
+using Mistelix.Backends.ThumbnailCache;
+
+namespace Mistelix.Performance
+{
+	// Performance testing of GetThumbnail operations
+	public class SlideImagePerf
+	{
+		/*
+			GNOME cache -> 	00:00:05.6705334 (creating cache)
+					00:00:00.2680794.(once cached)
+			
+			With no cache -> 00:00:28.8975945 (using Pixbuf)
+		*/
+		static void Main ()
+		{
+			string[] files;
+			Provider provider = Factory.Provider;
+			Pixbuf buf;
+			TimeSpan time;
+			int nulls = 0;
+
+			files = Directory.GetFiles ("/home/jordi/Desktop/berna"); // Directory with images to test
+
+			Stopwatch stopWatch = new Stopwatch ();
+			stopWatch.Start ();
+			foreach (string file in files)
+			{
+				buf = provider.GetThumbnail (file, 96, 96);
+	
+				if (buf == null) {
+					nulls++;
+					buf = new Pixbuf (file);
+				}
+
+				buf.Dispose ();
+			}
+
+			stopWatch.Stop ();
+			time = stopWatch.Elapsed;
+
+			Console.WriteLine ("Time needed {0}. Total files {1}, thumbnailed {2}, skipped {3}", time, files.Length, files.Length - nulls, nulls);
+			return;
+		}
+	}
+}
diff --git a/src/Backends/ThumbnailCache/Factory.cs b/src/Backends/ThumbnailCache/Factory.cs
new file mode 100644
index 0000000..36a805b
--- /dev/null
+++ b/src/Backends/ThumbnailCache/Factory.cs
@@ -0,0 +1,59 @@
+//
+// Copyright (C) 2009 Jordi Mas i Hernandez, jmas softcatala org
+//
+// 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.Runtime.InteropServices;
+using Gdk;
+
+using Mistelix.Core;
+
+namespace Mistelix.Backends.ThumbnailCache
+{
+	//
+	// Returns the appropiate class for managing Thumbnails
+	// 
+	public static class Factory
+	{
+		static Provider provider;
+
+		static Factory ()
+		{
+			// See: http://www.mono-project.com/FAQ:_Technical
+			int os = (int) System.Environment.OSVersion.Platform;
+			if (os == 4 || os == 6 || os == 128) {
+				provider = new Gnome ();
+				if (provider.Installed == false)
+					provider = null;
+			}
+
+			if (provider == null)
+				provider = new None ();
+	
+			Logger.Debug ("Factory.Factory. Provider {0}", provider);
+		}
+		
+		public static Provider Provider {
+			get {return provider; }
+		}
+	}
+}
diff --git a/src/Backends/ThumbnailCache/Gnome.cs b/src/Backends/ThumbnailCache/Gnome.cs
new file mode 100644
index 0000000..a211fc9
--- /dev/null
+++ b/src/Backends/ThumbnailCache/Gnome.cs
@@ -0,0 +1,180 @@
+//
+// Copyright (C) 2009 Jordi Mas i Hernandez, jmas softcatala org
+//
+// 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.IO;
+using System.Runtime.InteropServices;
+using Gdk;
+
+using Mistelix.Core;
+
+namespace Mistelix.Backends.ThumbnailCache
+{
+	//
+	// This class uses Gnome-desktop thumbnailing infrastructure for loading and storing thumbnails
+	// It allows to reuse the thumbnails created already by Nautilus and other GNOME applications
+	// 
+	// See: http://library.gnome.org/devel/gnome-desktop/stable/
+	// 
+	public class Gnome : Provider
+	{
+		[DllImport ("libgnome-desktop-2")]
+		static extern IntPtr gnome_desktop_thumbnail_factory_new (int size);
+
+		[DllImport ("libgnome-desktop-2")] // returns GdkPixbuf * 
+		static extern IntPtr gnome_desktop_thumbnail_factory_generate_thumbnail (IntPtr factory, string uri, string mime_type);
+
+		[DllImport ("libgnome-desktop-2")]
+		static extern void gnome_desktop_thumbnail_factory_save_thumbnail (IntPtr factory, IntPtr thumbnail, string uri, ulong time);
+
+		[DllImport ("libgnome-desktop-2")]
+		static extern IntPtr gnome_desktop_thumbnail_factory_lookup (IntPtr factory, string uri, ulong time);
+
+	        [DllImport("libglib-2.0")]
+		static extern IntPtr g_filename_to_uri (IntPtr filename, IntPtr hostname, IntPtr error);
+
+		[DllImport("libgio-2.0")]
+		static extern IntPtr g_content_type_guess (IntPtr filename, out byte data, UIntPtr data_size, out bool result_uncertain);
+
+		[DllImport ("libgio-2.0")]
+		static extern IntPtr g_file_new_for_uri (string uri);
+
+		[DllImport ("libgio-2.0")]
+		static extern ulong g_file_info_get_attribute_uint64 (IntPtr file, string attribute);
+
+		[DllImport("libgio-2.0")] // returns GFileInfo *
+		static extern  IntPtr g_file_query_info (IntPtr gfile, string attributes, int flags, IntPtr cancellable, out IntPtr error);
+
+		[DllImport("libgio-2.0")]
+		static extern void g_file_info_get_modification_time (IntPtr raw, IntPtr result);
+
+		[DllImport("libgobject-2.0")]
+		static extern void g_object_unref (IntPtr raw);
+
+		IntPtr factory_normal;
+		IntPtr factory_large;
+
+		const int GNOME_DESKTOP_THUMBNAIL_SIZE_NORMAL = 0;
+		const int GNOME_DESKTOP_THUMBNAIL_SIZE_LARGE = 1;
+	
+		public Gnome ()
+		{
+			try {
+				GLib.GType.Init (); // The following calls assume that Glib is initialized
+				factory_normal = gnome_desktop_thumbnail_factory_new (GNOME_DESKTOP_THUMBNAIL_SIZE_NORMAL);
+				factory_large = gnome_desktop_thumbnail_factory_new (GNOME_DESKTOP_THUMBNAIL_SIZE_LARGE);
+			}
+			catch (Exception e) {
+				Logger.Error ("Gnome.Gnome. Unhandled exception {0}", e);
+			}
+		}
+
+		public override bool Installed {
+			get {
+				return (factory_normal != IntPtr.Zero);
+			}
+		}
+
+		public override Gdk.Pixbuf GetThumbnail (string filename, int width, int height)
+		{
+			try {
+				IntPtr pix_raw, path_raw, uri_raw, mime_raw, factory_raw, thumbnail_raw;
+				string uri, mime_type, thumbnail_file;
+				byte data;
+				ulong data_size = 0, time;
+				bool result_uncertain;
+				Pixbuf pix;
+
+				path_raw = GLib.Marshaller.StringToPtrGStrdup (filename);
+				if (path_raw == IntPtr.Zero)
+					return null;
+
+				// Get URI
+				uri_raw = g_filename_to_uri (path_raw, IntPtr.Zero, IntPtr.Zero);
+				uri = GLib.Marshaller.Utf8PtrToString (uri_raw);
+
+				factory_raw = (width > 128 || height > 128) ? factory_large : factory_normal;
+
+				time = GetTimeModified (uri);
+				// Verifies that the thumbnail exists and it is updated
+				thumbnail_raw = gnome_desktop_thumbnail_factory_lookup (factory_raw, uri, time);
+				thumbnail_file = GLib.Marshaller.Utf8PtrToString (thumbnail_raw);
+				GLib.Marshaller.Free (thumbnail_raw);
+
+				// Does thumbnail file exists already?
+				if (String.IsNullOrEmpty (thumbnail_file) == false) {
+					Logger.Debug ("Gnome.GetThumbnail. Cached image found {0}", thumbnail_file);
+					GLib.Marshaller.Free (uri_raw);
+					GLib.Marshaller.Free (path_raw);
+					return new Pixbuf (thumbnail_file);
+				}
+
+				// Get MimeType
+				mime_raw = g_content_type_guess (path_raw, out data, new UIntPtr (data_size), out result_uncertain);
+				mime_type = GLib.Marshaller.PtrToStringGFree (mime_raw);
+				pix_raw = gnome_desktop_thumbnail_factory_generate_thumbnail (factory_raw, uri, mime_type);
+
+				GLib.Marshaller.Free (uri_raw);
+				GLib.Marshaller.Free (path_raw);
+
+				pix = new Gdk.Pixbuf (pix_raw);
+				StoreThumbnail (uri,  pix);
+				return pix;
+			} 
+			catch (Exception e) {
+				Logger.Error ("Gnome.GetThumbnail. Error {0}", e);
+				return null;
+			}
+		}
+
+		public override void StoreThumbnail (string uri, Gdk.Pixbuf pixbuf)
+		{
+			IntPtr factory_raw;
+			ulong time;
+
+			try 
+			{
+				time = GetTimeModified (uri);
+				factory_raw = (pixbuf.Width > 128 || pixbuf.Height > 128) ? factory_large : factory_normal;
+				gnome_desktop_thumbnail_factory_save_thumbnail (factory_raw, pixbuf.Handle, uri, time);
+				Logger.Debug ("Gnome.StoreThumbnail. Cached image {0}", uri);
+			}
+
+			catch (Exception e) {
+				Logger.Error ("Gnome.StoreThumbnail. Error {0}", e);
+				return;
+			}
+		}
+
+		ulong GetTimeModified (string uri)
+		{
+			ulong time;
+			IntPtr file_raw, fileinfo_raw, error_raw;
+	
+			file_raw  = g_file_new_for_uri (uri);
+			fileinfo_raw =  g_file_query_info (file_raw, "time::modified", 0, IntPtr.Zero, out error_raw);
+			time = g_file_info_get_attribute_uint64 (fileinfo_raw, "time::modified");
+			return time;
+		}
+	}
+}
diff --git a/src/Backends/ThumbnailCache/None.cs b/src/Backends/ThumbnailCache/None.cs
new file mode 100644
index 0000000..01b1cd4
--- /dev/null
+++ b/src/Backends/ThumbnailCache/None.cs
@@ -0,0 +1,56 @@
+//
+// Copyright (C) 2009 Jordi Mas i Hernandez, jmas softcatala org
+//
+// 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.Runtime.InteropServices;
+using Gdk;
+
+using Mistelix.Core;
+
+namespace Mistelix.Backends.ThumbnailCache
+{
+	//
+	// For platforms that does not support a thumbnail cache
+	// 
+	public class None : Provider
+	{
+		public None ()
+		{
+
+		}
+
+		public override bool Installed {
+			get { return true;}
+		}
+
+		public override Gdk.Pixbuf GetThumbnail (string filename, int width, int height)
+		{
+			return null;
+		}
+	
+		public override void StoreThumbnail (string filename, Gdk.Pixbuf pixbuf)
+		{
+
+		}
+	}
+}
diff --git a/src/Backends/ThumbnailCache/Provider.cs b/src/Backends/ThumbnailCache/Provider.cs
new file mode 100644
index 0000000..d39fe6f
--- /dev/null
+++ b/src/Backends/ThumbnailCache/Provider.cs
@@ -0,0 +1,42 @@
+//
+// Copyright (C) 2009 Jordi Mas i Hernandez, jmas softcatala org
+//
+// 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.Runtime.InteropServices;
+using Gdk;
+
+namespace Mistelix.Backends.ThumbnailCache
+{
+	//
+	// Describes the services that a ThumbnailCache should implement
+	// 
+	public abstract class Provider
+	{
+		public abstract bool Installed {get;}
+
+		// Get a thumbnail. Returns null if not possible to get a thumbnail
+		// The call does not guaranty that the thumbnail will match the request width & height
+		public abstract Gdk.Pixbuf GetThumbnail (string filename, int width, int height);
+		public abstract void StoreThumbnail (string filename, Gdk.Pixbuf pixbuf);
+	}
+}
diff --git a/src/Core/ThumbnailSizeManager.cs b/src/Core/ThumbnailSizeManager.cs
index 1c35d43..dbf7ec1 100644
--- a/src/Core/ThumbnailSizeManager.cs
+++ b/src/Core/ThumbnailSizeManager.cs
@@ -34,6 +34,7 @@ namespace Mistelix.Core
 		static Resolution[] sizes;
 		static ThumbnailSizeManager ()
 		{
+			// See: http://jens.triq.net/thumb-spec.php (Thumbnail Managing Standard)
 			sizes = new Resolution [4];
 			sizes[0] = new Resolution (Catalog.GetString ("Small (64x64 pixels)"), 64, 64);
 			sizes[1] = new Resolution (Catalog.GetString ("Medium (96x96 pixels)"), 96, 96);
diff --git a/src/DataModel/SlideShowProjectElement.cs b/src/DataModel/SlideShowProjectElement.cs
index 9421e55..c03df4b 100644
--- a/src/DataModel/SlideShowProjectElement.cs
+++ b/src/DataModel/SlideShowProjectElement.cs
@@ -71,8 +71,12 @@ namespace Mistelix.DataModel
 		{
 			if (width <= 0 || height <= 0)
 				throw new ArgumentException (String.Format ("SlideShowProjectElement->GetThumbnail. Width {0} and height {1} should be > 0", width, height));
-			
-			Gdk.Pixbuf im = new Gdk.Pixbuf (images[0].image);
+
+			Gdk.Pixbuf im = Backends.ThumbnailCache.Factory.Provider.GetThumbnail (images[0].image, width, height);
+
+			if (im == null)
+				im = new Gdk.Pixbuf (images[0].image);
+
 			int max = Math.Max (im.Width, im.Height);
 			Gdk.Pixbuf scaled = im.ScaleSimple (width * im.Width / max, height * im.Height / max, InterpType.Nearest);
 			im.Dispose ();
diff --git a/src/Makefile.am b/src/Makefile.am
index 71c4cb4..4f47677 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -77,7 +77,11 @@ MISTELIX_CSDISTFILES =				\
 	$(srcdir)/Backends/GStreamer/Thumbnail.cs \
 	$(srcdir)/Backends/GStreamer/SlideShow.cs \
 	$(srcdir)/Backends/GStreamer/Plugins.cs \
-	$(srcdir)/Backends/OS/Unix.cs
+	$(srcdir)/Backends/OS/Unix.cs \
+	$(srcdir)/Backends/ThumbnailCache/Provider.cs \
+	$(srcdir)/Backends/ThumbnailCache/Factory.cs \
+	$(srcdir)/Backends/ThumbnailCache/Gnome.cs \
+	$(srcdir)/Backends/ThumbnailCache/None.cs
 
 ASSEMBLIES = \
 	 $(MISTELIX_LIBS)    		\
diff --git a/src/Widgets/FileView.cs b/src/Widgets/FileView.cs
index a10c416..35f1bf8 100644
--- a/src/Widgets/FileView.cs
+++ b/src/Widgets/FileView.cs
@@ -110,18 +110,13 @@ namespace Mistelix.Widgets
 		protected virtual void Dispose (bool disposing)
 		{
 			Logger.Debug ("Fileview.Disposing");
-			store.Foreach (delegate (TreeModel model, TreePath path, TreeIter iter)  
-			{
-				Gdk.Pixbuf im = (Gdk.Pixbuf) store.GetValue (iter, COL_PIXBUF);
-				im.Dispose ();
-
-				return false;
-			});
-
+			Clean ();
+			
 			if (thumbnailing != null) {
 				thumbnailing.CancelAsync ();
 				thumbnailing.Dispose ();
 			}
+			def_image.Dispose ();
 		}
 
 		public void LoadElements ()
@@ -133,7 +128,7 @@ namespace Mistelix.Widgets
 				return;
 
 			// first clear the store
-			store.Clear ();
+			Clean ();
 
 			if (thumbnailing != null)
 				thumbnailing.Dispose ();
@@ -154,6 +149,19 @@ namespace Mistelix.Widgets
 			thumbnailing.RunWorkerAsync (store);
 		}
 
+		void Clean ()
+		{
+			store.Foreach (delegate (TreeModel model, TreePath path, TreeIter iter)  
+			{
+				Gdk.Pixbuf im = (Gdk.Pixbuf) store.GetValue (iter, COL_PIXBUF);
+				if (def_image != im)
+					im.Dispose ();
+
+				return false;
+			});
+			store.Clear ();
+		}
+
 		void CreateDefaultImage ()
 		{
 			const int channels = 4;
diff --git a/src/Widgets/ImagesFileView.cs b/src/Widgets/ImagesFileView.cs
index 03d8d07..5feabfc 100644
--- a/src/Widgets/ImagesFileView.cs
+++ b/src/Widgets/ImagesFileView.cs
@@ -130,7 +130,11 @@ namespace Mistelix.Widgets
 						return true;
 
 					string file = (string) store.GetValue (iter, COL_PATH);
-					Gdk.Pixbuf im = new Gdk.Pixbuf (file);
+					Gdk.Pixbuf im = Backends.ThumbnailCache.Factory.Provider.GetThumbnail (file, thumbnail_width, thumbnail_height);
+
+					if (im == null)
+						im = new Gdk.Pixbuf (file);
+
 					int max = Math.Max (im.Width, im.Height);
 					Gdk.Pixbuf scaled = im.ScaleSimple (thumbnail_width * im.Width / max, thumbnail_height * im.Height / max, InterpType.Nearest);
 



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