Show total number of results for google driver too. Helps to know if my query resulte...
[beagle.git] / search / Tiles / Tile.cs
blob6e09b390fb18b46993d216d17d54ea9a0ac39f68
1 using System;
2 using System.Collections;
3 using System.Runtime.InteropServices;
4 using System.Text.RegularExpressions;
5 using System.Diagnostics;
6 using Mono.Unix;
8 using Gtk;
9 using Beagle;
10 using Beagle.Util;
12 namespace Search.Tiles {
14 public abstract class Tile : Gtk.EventBox {
16 public Tile (Hit hit, Query query) : base ()
18 AboveChild = true;
19 AppPaintable = true;
20 CanFocus = true;
22 this.hit = hit;
23 this.timestamp = hit.Timestamp;
24 this.score = hit.Score;
25 this.query = query;
26 this.group = TileGroup.Documents;
28 Gtk.Drag.SourceSet (this, Gdk.ModifierType.Button1Mask,
29 targets, Gdk.DragAction.Copy | Gdk.DragAction.Move);
31 hbox = new Gtk.HBox (false, 5);
32 hbox.BorderWidth = 2;
33 hbox.Show ();
35 icon = new Gtk.Image ();
36 icon.Show ();
37 HBox.PackStart (icon, false, false, 0);
39 Add (hbox);
42 private Beagle.Hit hit;
43 public Beagle.Hit Hit {
44 get { return hit; }
47 private Beagle.Query query;
48 public Beagle.Query Query {
49 get { return query; }
52 private TileGroup group;
53 public TileGroup Group {
54 get { return group; }
55 set { group = value; }
58 private Gtk.HBox hbox;
59 protected Gtk.HBox HBox {
60 get { return hbox; }
63 private Gtk.Image icon;
64 public Gtk.Image Icon {
65 get { return icon; }
66 set { icon = value; }
69 private string title;
70 public virtual string Title {
71 get { return title; }
72 set { title = value; }
75 private DateTime timestamp;
76 public virtual DateTime Timestamp {
77 get { return timestamp; }
78 set { timestamp = value; }
81 private double score;
82 public virtual double Score {
83 get { return score; }
84 set { score = value; }
87 protected bool EnableOpenWith = false;
89 static Gtk.TargetEntry[] targets = new Gtk.TargetEntry[] {
90 new Gtk.TargetEntry ("text/uri-list", 0, 0)
93 public event EventHandler Selected;
95 protected override void OnDragBegin (Gdk.DragContext context)
97 if (!icon.Visible)
98 return;
100 WidgetFu.SetDragImage (context, icon);
103 protected override void OnDragDataGet (Gdk.DragContext dragContext,
104 Gtk.SelectionData selectionData,
105 uint info, uint time)
107 byte[] data = System.Text.Encoding.UTF8.GetBytes (Hit.EscapedUri + "\r\n");
108 selectionData.Set (selectionData.Target, 8, data);
111 protected override void OnSizeRequested (ref Gtk.Requisition req)
113 // FIXME: "base.OnSizeRequested (ref req)" should work,
114 // but it doesn't
115 req = hbox.SizeRequest ();
117 int pad = (int)StyleGetProperty ("focus-line-width") +
118 (int)StyleGetProperty ("focus-padding") + 1;
119 req.Width += 2 * (pad + Style.Xthickness);
120 req.Height += 2 * (pad + Style.Ythickness);
123 protected override void OnSizeAllocated (Gdk.Rectangle alloc)
125 int pad = (int)StyleGetProperty ("focus-line-width") +
126 (int)StyleGetProperty ("focus-padding") + 1;
128 alloc.X += pad + Style.Xthickness;
129 alloc.Width -= pad + Style.Xthickness;
130 alloc.Y += pad + Style.Ythickness;
131 alloc.Height -= pad + Style.Ythickness;
133 base.OnSizeAllocated (alloc);
136 protected override bool OnExposeEvent (Gdk.EventExpose evt)
138 if (!IsDrawable)
139 return false;
141 GdkWindow.DrawRectangle (Style.BaseGC (State), true,
142 evt.Area.X, evt.Area.Y,
143 evt.Area.Width, evt.Area.Height);
145 if (base.OnExposeEvent (evt))
146 return true;
148 if (HasFocus) {
149 Gdk.Rectangle alloc = Allocation;
150 int focusPad = (int)StyleGetProperty ("focus-padding");
152 int x = focusPad + Style.Xthickness;
153 int y = focusPad + Style.Ythickness;
154 int width = alloc.Width - 2 * (focusPad + Style.Xthickness);
155 int height = alloc.Height - 2 * (focusPad + Style.Ythickness);
156 Style.PaintFocus (Style, GdkWindow, State, evt.Area, this,
157 null, x, y, width, height);
160 return false;
163 ///////////////////////////////////////////////////
165 public ArrayList actions = new ArrayList ();
166 public ICollection Actions {
167 get { return actions; }
170 protected void AddAction (TileAction action)
172 actions.Add (action);
175 private void ShowPopupMenu ()
177 Gtk.Menu menu = new Gtk.Menu ();
179 ActionMenuItem mi = new ActionMenuItem (new TileAction (Catalog.GetString ("Open"), Stock.Open, Open));
180 menu.Append (mi);
182 #if ENABLE_OPEN_WITH
183 if (EnableOpenWith) {
184 OpenWithMenu owm = new OpenWithMenu (Hit ["beagle:MimeType"]);
185 owm.ApplicationActivated += OpenWith;
186 owm.AppendToMenu (menu);
188 #endif
190 if (Actions.Count > 0) {
191 SeparatorMenuItem si = new SeparatorMenuItem ();
192 menu.Append (si);
194 foreach (TileAction action in Actions) {
195 mi = new ActionMenuItem (action);
196 menu.Append (mi);
200 menu.ShowAll ();
201 menu.Popup ();
204 ///////////////////////////////////////////////////
206 protected override bool OnButtonPressEvent (Gdk.EventButton b)
208 GrabFocus ();
210 if (b.Button == 3) {
211 ShowPopupMenu ();
212 return true;
213 } else if (b.Type == Gdk.EventType.TwoButtonPress) {
214 Open ();
215 if (b.Button == 2 || ((b.State & Gdk.ModifierType.ShiftMask) != 0))
216 Gtk.Application.Quit ();
217 return true;
220 return base.OnButtonPressEvent (b);
223 protected override bool OnFocusInEvent (Gdk.EventFocus f)
225 if (Selected != null)
226 Selected (this, EventArgs.Empty);
227 return base.OnFocusInEvent (f);
230 protected override bool OnKeyPressEvent (Gdk.EventKey k)
232 if (k.Key == Gdk.Key.Return || k.Key == Gdk.Key.KP_Enter) {
233 Open ();
234 if ((k.State & Gdk.ModifierType.ShiftMask) != 0)
235 Gtk.Application.Quit ();
236 return true;
239 return base.OnKeyPressEvent (k);
242 protected virtual void LoadIcon (Gtk.Image image, int size)
244 // This is a hack to prevent large mime icons when we
245 // dont have a thumbnail.
246 if (size > 48)
247 size = 48;
249 image.Pixbuf = WidgetFu.LoadMimeIcon (hit.MimeType, size);
252 string snippet;
254 protected void RequestSnippet ()
256 if (snippet != null)
257 EmitGotSnippet ();
258 else {
259 SnippetRequest sreq = new SnippetRequest (query, hit);
260 sreq.RegisterAsyncResponseHandler (typeof (SnippetResponse), SnippetResponseReceived);
261 sreq.SendAsync ();
265 private void SnippetResponseReceived (ResponseMessage response)
267 // The returned snippet uses
268 // <font color="..."><b>blah</b></font>
269 // to mark matches. The rest of the snippet might be HTML, or
270 // it might be plain text, including unescaped '<'s and '&'s.
271 // So we escape it, fix the match highlighting, and leave any
272 // other tags escaped.
274 // FIXME: hacky, fix the snippeting in the daemon
275 snippet = GLib.Markup.EscapeText (((SnippetResponse)response).Snippet);
276 snippet = Regex.Replace (snippet, "&lt;font color=&quot;.*?&quot;&gt;&lt;b&gt;(.*?)&lt;/b&gt;&lt;/font&gt;", "<b>$1</b>");
278 EmitGotSnippet ();
281 private void EmitGotSnippet ()
283 if (snippet != null && snippet != "" && GotSnippet != null)
284 GotSnippet (snippet);
287 public delegate void GotSnippetHandler (string snippet);
288 public event GotSnippetHandler GotSnippet;
290 protected virtual DetailsPane GetDetails ()
292 return null;
295 DetailsPane details;
296 public Gtk.Widget Details {
297 get {
298 if (details == null) {
299 details = GetDetails ();
300 if (details != null) {
301 if (details.Icon.Pixbuf == null)
302 LoadIcon (details.Icon, 128);
304 if (details.Snippet != null) {
305 GotSnippet += details.GotSnippet;
306 RequestSnippet ();
309 details.Show ();
312 return details;
316 public virtual void Open ()
318 System.Console.WriteLine ("Warning: Open method not implemented for this tile type");
321 #if ENABLE_OPEN_WITH
322 private void OpenWith (Gnome.Vfs.MimeApplication mime_application)
324 GLib.List uri_list = new GLib.List (typeof (string));
325 uri_list.Append (Hit.EscapedUri);
326 mime_application.Launch (uri_list);
328 #endif
330 protected void OpenFromMime (Hit hit)
332 string command = null, item;
333 bool expects_uris = false;
335 // FIXME: This is evil. Nautilus should be handling
336 // inode/directory, not just x-directory/normal
337 if (hit.MimeType == "inode/directory")
338 hit.MimeType = "x-directory/normal";
340 #if ENABLE_DESKTOP_LAUNCH
341 command = "desktop-launch";
342 expects_uris = true;
343 #else
344 GnomeFu.VFSMimeApplication app;
345 app = GnomeFu.GetDefaultAction (hit.MimeType);
346 if (app.command != null) {
347 command = app.command;
348 expects_uris = (app.expects_uris != GnomeFu.VFSMimeApplicationArgumentType.Path);
350 #endif
351 if (command == null) {
352 Console.WriteLine ("Can't open MimeType '{0}'", hit.MimeType);
353 return;
356 if (expects_uris)
357 item = hit.EscapedUri;
358 else
359 item = hit.Path;
361 // Sometimes the command is 'quoted'
362 if (command.IndexOf ('\'') == 0 && command.LastIndexOf ('\'') == command.Length - 1)
363 command = command.Trim ('\'');
365 // This won't work if a program really has a space in
366 // the command filename, but I think other things would
367 // break with that too, and in practice it doesn't seem to
368 // happen.
370 // A bigger issue is that the arguments are split up by
371 // spaces, so quotation marks used to indicate a single
372 // entry in the argv won't work. This probably should
373 // be fixed.
374 string[] arguments = null;
375 int idx = command.IndexOf (' ');
376 if (idx != -1) {
377 arguments = command.Substring (idx + 1).Split (' ');
378 command = command.Substring (0, idx);
381 string[] argv;
382 if (arguments == null)
383 argv = new string [] { command, item };
384 else {
385 argv = new string [arguments.Length + 2];
386 argv [0] = command;
387 argv [argv.Length - 1] = item;
388 Array.Copy (arguments, 0, argv, 1, arguments.Length);
391 Console.WriteLine ("Cmd: {0}", command);
392 Console.WriteLine ("Arg: {0}", String.Join (" ", argv, 1, argv.Length - 2));
393 Console.WriteLine ("Itm: {0}", item);
395 SafeProcess p = new SafeProcess ();
396 p.Arguments = argv;
398 try {
399 p.Start ();
400 } catch (Exception e) {
401 Console.WriteLine ("Error in OpenFromMime: " + e);
405 public void OpenFromUri (Uri uri)
407 OpenFromUri (UriFu.UriToEscapedString (uri));
410 public void OpenFromUri (string uri)
412 #if ENABLE_DESKTOP_LAUNCH
413 SafeProcess p = new SafeProcess ();
414 p.Arguments = new string[] { "desktop-launch", uri };
416 try {
417 p.Start ();
418 } catch (Exception e) {
419 Console.WriteLine ("Could not load handler for {0}: {1}", uri, e);
421 #else
422 try {
423 Gnome.Url.Show (uri);
424 } catch (Exception e) {
425 Console.WriteLine ("Could not load handler for {0}: {1}", uri, e);
427 #endif