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 Beagle
.Hit Hit
;
32 public bool Succeeded
;
34 public ThumbnailRequest (Gtk
.Image image
, Beagle
.Hit hit
, int size
)
41 public static ThumbnailRequest
Select (IEnumerable thumbnails
)
43 ThumbnailRequest first
= null;
46 foreach (ThumbnailRequest req
in thumbnails
) {
48 // FIXME: we ought to be able to just look at
49 // req.Image.IsMapped. But for some reason, the
50 // images are still showing up as mapped even
51 // when their parents aren't, which seems
52 // impossible to me from looking at the code,
54 for (w
= req
.Image
; w
!= null; w
= w
.Parent
) {
68 public bool SetThumbnailIcon (Gtk
.Image image
, Beagle
.Hit hit
, int size
)
70 DateTime mtime
= (hit
.FileInfo
!= null) ? hit
.FileInfo
.LastWriteTime
: DateTime
.Now
;
72 if (hit
.MimeType
== null ||
73 !factory
.CanThumbnail (hit
.UriAsString
, hit
.MimeType
, mtime
))
76 string thumbnail
= Gnome
.Thumbnail
.PathForUri (hit
.UriAsString
, Gnome
.ThumbnailSize
.Normal
);
77 bool failed_thumb
= factory
.HasValidFailedThumbnail (hit
.UriAsString
, mtime
);
79 if (! File
.Exists (thumbnail
) && ! failed_thumb
) {
81 in_queue
.Add (new ThumbnailRequest (image
, hit
, size
));
83 thread
= new Thread (GenerateThumbnails
);
93 Gdk
.Pixbuf icon
= new Gdk
.Pixbuf (thumbnail
);
97 int width
= icon
.Width
, height
= icon
.Height
;
98 if (icon
.Height
> size
) {
99 if (icon
.Width
> icon
.Height
) {
101 height
= (size
* icon
.Height
) / icon
.Width
;
104 width
= (size
* icon
.Width
) / icon
.Height
;
106 } else if (icon
.Width
> size
) {
108 height
= (size
* icon
.Height
) / icon
.Width
;
110 icon
= icon
.ScaleSimple (width
, height
, Gdk
.InterpType
.Bilinear
);
116 private void GenerateThumbnails ()
118 ThumbnailRequest req
;
122 if (in_queue
.Count
== 0) {
127 req
= ThumbnailRequest
.Select (in_queue
);
128 in_queue
.Remove (req
);
131 Gdk
.Pixbuf icon
= factory
.GenerateThumbnail (req
.Hit
.UriAsString
, req
.Hit
.MimeType
);
134 if (req
.Hit
.FileInfo
!= null)
135 factory
.CreateFailedThumbnail (req
.Hit
.UriAsString
, req
.Hit
.FileInfo
.LastWriteTime
);
137 factory
.SaveThumbnail (icon
, req
.Hit
.UriAsString
, DateTime
.Now
);
138 req
.Succeeded
= true;
143 GLib
.Idle
.Add (FinishSetThumbnail
);
147 private bool FinishSetThumbnail ()
149 ThumbnailRequest req
;
151 req
= (ThumbnailRequest
)out_queue
[0];
152 out_queue
.RemoveAt (0);
156 SetThumbnailIcon (req
.Image
, req
.Hit
, req
.Size
);