2 using System
.Collections
;
4 using System
.Threading
;
6 namespace Search
.Tiles
{
8 public class ThumbnailFactory
: Gtk
.Object
{
10 private Gnome
.ThumbnailFactory factory
= new Gnome
.ThumbnailFactory (Gnome
.ThumbnailSize
.Normal
);
11 private Thread thread
;
12 private ArrayList in_queue
= new ArrayList ();
13 private ArrayList out_queue
= new ArrayList ();
15 public ThumbnailFactory ()
17 Gtk
.Quit
.AddDestroy (1, this);
20 protected override void OnDestroyed ()
22 // Force the thumbnailing thread to exit cleanly once it
23 // finishes the current thumbnail
28 private class ThumbnailRequest
{
29 public Gtk
.Image Image
;
30 public string ThumbnailFile
;
31 public Beagle
.Hit Hit
;
33 public bool Succeeded
;
35 public ThumbnailRequest (Gtk
.Image image
, string thumbnail_file
, Beagle
.Hit hit
, int size
)
38 ThumbnailFile
= thumbnail_file
;
43 public static ThumbnailRequest
Select (IEnumerable thumbnails
)
45 ThumbnailRequest first
= null;
48 foreach (ThumbnailRequest req
in thumbnails
) {
50 // FIXME: we ought to be able to just look at
51 // req.Image.IsMapped. But for some reason, the
52 // images are still showing up as mapped even
53 // when their parents aren't, which seems
54 // impossible to me from looking at the code,
56 for (w
= req
.Image
; w
!= null; w
= w
.Parent
) {
70 public bool SetThumbnailIcon (Gtk
.Image image
, Beagle
.Hit hit
, int size
)
72 DateTime mtime
= (hit
.FileInfo
!= null) ? hit
.FileInfo
.LastWriteTime
: DateTime
.Now
;
74 if (hit
.MimeType
== null ||
75 !factory
.CanThumbnail (hit
.EscapedUri
, hit
.MimeType
, mtime
))
78 string thumbnail
= Gnome
.Thumbnail
.PathForUri (hit
.EscapedUri
, Gnome
.ThumbnailSize
.Normal
);
79 bool failed_thumb
= factory
.HasValidFailedThumbnail (hit
.EscapedUri
, mtime
);
81 if (! File
.Exists (thumbnail
) && ! failed_thumb
) {
83 in_queue
.Add (new ThumbnailRequest (image
, thumbnail
, hit
, size
));
85 thread
= new Thread (GenerateThumbnails
);
95 Gdk
.Pixbuf icon
= new Gdk
.Pixbuf (thumbnail
);
99 int width
= icon
.Width
, height
= icon
.Height
;
100 if (icon
.Height
> size
) {
101 if (icon
.Width
> icon
.Height
) {
103 height
= (size
* icon
.Height
) / icon
.Width
;
106 width
= (size
* icon
.Width
) / icon
.Height
;
108 } else if (icon
.Width
> size
) {
110 height
= (size
* icon
.Height
) / icon
.Width
;
112 icon
= icon
.ScaleSimple (width
, height
, Gdk
.InterpType
.Bilinear
);
118 private void GenerateThumbnails ()
120 ThumbnailRequest req
;
124 if (in_queue
.Count
== 0) {
129 req
= ThumbnailRequest
.Select (in_queue
);
130 in_queue
.Remove (req
);
133 Gdk
.Pixbuf icon
= factory
.GenerateThumbnail (req
.Hit
.EscapedUri
, req
.Hit
.MimeType
);
136 if (req
.Hit
.FileInfo
!= null)
137 factory
.CreateFailedThumbnail (req
.Hit
.EscapedUri
, req
.Hit
.FileInfo
.LastWriteTime
);
139 factory
.SaveThumbnail (icon
, req
.Hit
.EscapedUri
, DateTime
.Now
);
141 if (File
.Exists (req
.ThumbnailFile
))
142 req
.Succeeded
= true;
147 GLib
.Idle
.Add (FinishSetThumbnail
);
151 private bool FinishSetThumbnail ()
153 ThumbnailRequest req
;
155 req
= (ThumbnailRequest
)out_queue
[0];
156 out_queue
.RemoveAt (0);
160 SetThumbnailIcon (req
.Image
, req
.Hit
, req
.Size
);