4 // Copyright (C) 2004 Novell, Inc.
8 // Permission is hereby granted, free of charge, to any person obtaining a copy
9 // of this software and associated documentation files (the "Software"), to deal
10 // in the Software without restriction, including without limitation the rights
11 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 // copies of the Software, and to permit persons to whom the Software is
13 // furnished to do so, subject to the following conditions:
15 // The above copyright notice and this permission notice shall be included in all
16 // copies or substantial portions of the Software.
18 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
29 using System
.Collections
;
37 using BU
= Beagle
.Util
;
42 public class TypeMenuItem
: Gtk
.MenuItem
{
46 public TypeMenuItem (string label
, string type
) : base (label
)
52 public class BestWindow
: Gtk
.Window
{
54 public BestWindow (string query
) : base (WindowType
.Toplevel
)
59 public BestWindow () : base (WindowType
.Toplevel
)
64 public void FocusEntry () {
65 entry
.SelectRegion (0, -1);
66 entry
.GtkEntry
.GrabFocus ();
69 public void FocusEntryHandler (object o
, EventArgs args
) {
73 Gtk
.AccelGroup accel_group
;
74 BU
.GlobalKeybinder global_keys
;
76 void CreateWindow (string query
)
78 Title
= Best
.DefaultWindowTitle
;
80 DeleteEvent
+= new DeleteEventHandler (this.DoDelete
);
81 MapEvent
+= new MapEventHandler (MapIt
);
82 UnmapEvent
+= new UnmapEventHandler (UnmapIt
);
84 Icon
= Images
.GetPixbuf ("best.png");
86 Widget content
= CreateContents ();
88 VBox main
= new VBox (false, 3);
89 main
.PackStart (content
, true, true, 3);
96 root
= new SimpleRootTile ();
102 accel_group
= new Gtk
.AccelGroup ();
103 this.AddAccelGroup (accel_group
);
104 global_keys
= new BU
.GlobalKeybinder (accel_group
);
106 // Close window (Ctrl-W)
107 global_keys
.AddAccelerator (new EventHandler (this.HideWindowHandler
),
109 Gdk
.ModifierType
.ControlMask
,
110 Gtk
.AccelFlags
.Visible
);
112 // Close window (Escape)
113 global_keys
.AddAccelerator (new EventHandler (this.HideWindowHandler
),
114 (uint) Gdk
.Key
.Escape
,
116 Gtk
.AccelFlags
.Visible
);
118 // Show source (Ctrl+U)
119 global_keys
.AddAccelerator (new EventHandler (this.ShowSource
),
121 Gdk
.ModifierType
.ControlMask
,
122 Gtk
.AccelFlags
.Visible
);
124 // Focus Entry (Ctrl+L)
125 global_keys
.AddAccelerator (new EventHandler (this.FocusEntryHandler
),
127 Gdk
.ModifierType
.ControlMask
,
128 Gtk
.AccelFlags
.Visible
);
130 // Previous Page (PageUp)
131 global_keys
.AddAccelerator (new EventHandler (this.PageBackHandler
),
132 (uint) Gdk
.Key
.Page_Up
,
134 Gtk
.AccelFlags
.Visible
);
136 // Next Page (PageDown)
137 global_keys
.AddAccelerator (new EventHandler (this.PageForwardHandler
),
138 (uint) Gdk
.Key
.Page_Down
,
140 Gtk
.AccelFlags
.Visible
);
142 //DBusisms.BeagleDown += OnBeagleDown;
151 //////////////////////////
153 int posX
= 0, posY
= 0;
155 public new void Present ()
162 public new void Hide ()
164 // FIXME: Hack, why does Hide () gets invoked twice, the second time with (0,0) as window position?
166 int new_posX
= 0, new_posY
= 0;
168 GetPosition (out new_posX
, out new_posY
);
170 if (new_posX
!= 0 && new_posY
!= 0) {
178 //////////////////////////
181 string hit_type
= null;
183 private void SetBusy (bool busy
)
186 this.GdkWindow
.Cursor
= new Gdk
.Cursor (Gdk
.CursorType
.Watch
);
188 this.GdkWindow
.Cursor
= null;
193 private void OnBeagleDown ()
199 private void DoDelete (object o
, DeleteEventArgs args
)
204 public bool WindowIsVisible
;
206 private void MapIt (object o
, MapEventArgs args
)
208 WindowIsVisible
= true;
211 private void UnmapIt (object o
, UnmapEventArgs args
)
213 WindowIsVisible
= false;
216 private void HideWindowHandler (object o
, EventArgs args
)
221 private void ShowSource (object o
, EventArgs args
)
223 Gtk
.Window win
= new Gtk
.Window ("Source");
224 win
.SetDefaultSize (800,500);
225 Gtk
.ScrolledWindow sw
= new ScrolledWindow ();
226 sw
.HscrollbarPolicy
= Gtk
.PolicyType
.Automatic
;
227 sw
.VscrollbarPolicy
= Gtk
.PolicyType
.Automatic
;
228 Gtk
.TextView view
= new Gtk
.TextView ();
229 view
.CursorVisible
= false;
230 view
.Editable
= false;
231 Gtk
.TextBuffer buffer
= view
.Buffer
;
232 buffer
.Text
= canvas
.Source
;
233 view
.Buffer
= buffer
;
239 //////////////////////////
241 private void PageForward ()
243 if (!root
.HitCollection
.CanPageForward
)
246 root
.HitCollection
.PageForward ();
250 private void PageBack ()
252 if (!root
.HitCollection
.CanPageBack
)
255 root
.HitCollection
.PageBack ();
259 private void PageForwardHandler (object o
, EventArgs args
)
264 private void PageBackHandler (object o
, EventArgs args
)
269 //////////////////////////
271 private Gnome
.Entry entry
;
273 private TileCanvas canvas
;
274 private SimpleRootTile root
;
275 private Gtk
.Label page_label
;
276 private Gtk
.Button back_button
;
277 private Gtk
.Button forward_button
;
278 private ArrayList menu_items
= new ArrayList ();
280 private Gtk
.Button
StockButton (string stockid
, string label
)
282 Gtk
.HBox button_contents
= new HBox (false, 0);
283 button_contents
.Show ();
284 Gtk
.Widget button_image
= new Gtk
.Image (stockid
, Gtk
.IconSize
.Button
);
285 button_image
.Show ();
286 button_contents
.PackStart (button_image
, false, false, 1);
287 Gtk
.Label button_label
= new Gtk
.Label (label
);
288 button_label
.Show ();
289 button_contents
.PackStart (button_label
, false, false, 1);
291 Gtk
.Button button
= new Gtk
.Button ();
292 button
.Add (button_contents
);
297 private Gtk
.OptionMenu
TypesOptionMenu ()
299 Gtk
.OptionMenu opt
= new Gtk
.OptionMenu ();
302 mi
= new TypeMenuItem (Catalog
.GetString ("Anywhere"), null);
303 this.menu_items
.Add (mi
);
304 mi
= new TypeMenuItem (Catalog
.GetString ("in Files"), "File");
305 this.menu_items
.Add (mi
);
306 mi
= new TypeMenuItem (Catalog
.GetString ("in Addressbook"), "Contact");
307 this.menu_items
.Add (mi
);
308 mi
= new TypeMenuItem (Catalog
.GetString ("in Mail"), "MailMessage");
309 this.menu_items
.Add (mi
);
310 mi
= new TypeMenuItem (Catalog
.GetString ("in Web Pages"), "WebHistory");
311 this.menu_items
.Add (mi
);
312 mi
= new TypeMenuItem (Catalog
.GetString ("in Chats"), "IMLog");
313 this.menu_items
.Add (mi
);
315 Gtk
.Menu menu
= new Gtk
.Menu ();
316 foreach (Gtk
.MenuItem item
in this.menu_items
)
323 private Gtk
.Widget
CreateContents ()
325 Gtk
.HBox entryLine
= new HBox (false, 3);
327 Gtk
.Label words
= new Gtk
.Label (Catalog
.GetString ("Search terms:"));
328 entryLine
.PackStart (words
, false, false, 3);
330 entry
= new Gnome
.Entry ("");
331 entry
.Activated
+= new EventHandler (this.DoSearch
);
332 entryLine
.PackStart (entry
, true, true, 3);
334 words
= new Gtk
.Label ("");
335 entryLine
.PackStart (words
, false, false, 3);
337 Gtk
.OptionMenu types
= TypesOptionMenu ();
338 types
.Changed
+= new EventHandler (this.ChangeType
);
339 entryLine
.PackStart (types
, false, false, 3);
341 Gtk
.HBox buttonContents
= new HBox (false, 0);
342 Gtk
.Widget buttonImg
= Beagle
.Images
.GetWidget ("icon-search.png");
343 buttonContents
.PackStart (buttonImg
, false, false, 1);
344 Gtk
.Label buttonLabel
= new Gtk
.Label (Catalog
.GetString ("Find"));
345 buttonContents
.PackStart (buttonLabel
, false, false, 1);
347 Gtk
.Button button
= new Gtk
.Button ();
348 button
.Add (buttonContents
);
349 button
.Clicked
+= new EventHandler (this.DoSearch
);
350 entryLine
.PackStart (button
, false, false, 3);
352 canvas
= new TileCanvas ();
355 HBox pager
= new HBox ();
356 page_label
= new Label ();
358 pager
.PackStart (page_label
, false, false, 3);
360 forward_button
= StockButton ("gtk-go-forward",
361 Catalog
.GetString ("Show More Results"));
362 forward_button
.Show ();
363 forward_button
.Clicked
+= new EventHandler (PageForwardHandler
);
364 pager
.PackEnd (forward_button
, false, false, 3);
366 back_button
= StockButton ("gtk-go-back",
367 Catalog
.GetString ("Show Previous Results"));
370 back_button
.Clicked
+= new EventHandler (PageBackHandler
);
371 pager
.PackEnd (back_button
, false, false, 3);
375 VBox contents
= new VBox (false, 3);
376 contents
.PackStart (entryLine
, false, true, 3);
377 contents
.PackStart (canvas
, true, true, 3);
378 contents
.PackStart (pager
, false, false, 3);
380 entryLine
.ShowAll ();
386 private void UpdatePage ()
388 //Console.WriteLine ("In UpdatePage");
389 back_button
.Sensitive
= root
.HitCollection
.CanPageBack
;
390 forward_button
.Sensitive
= root
.HitCollection
.CanPageForward
;
395 if (this.hit_type
== null)
396 results
= root
.HitCollection
.NumResults
;
398 results
= root
.HitCollection
.NumDisplayableResults
;
401 label
= Catalog
.GetString ("No results.");
402 } else if (root
.HitCollection
.FirstDisplayed
== 0) {
403 /* To translators: {0} is the current count of results shown of {1} in total, this is the message that is initially shown */
404 /* when results are returned to the user. */
405 label
= String
.Format (Catalog
.GetString ("Best <b>{0} results of {1}</b> are shown."),
406 root
.HitCollection
.LastDisplayed
+ 1,
409 /* To translators: {0} to {1} is the interval of results currently shown of {2} results in total*/
410 label
= String
.Format (Catalog
.GetString ("Results <b>{0} through {1} of {2}</b> are shown."),
411 root
.HitCollection
.FirstDisplayed
+ 1,
412 root
.HitCollection
.LastDisplayed
+ 1,
415 page_label
.Markup
= label
;
418 private string delayedQuery
= null;
420 private bool RunDelayedQuery ()
422 if (delayedQuery
!= null) {
423 string tmp
= delayedQuery
;
425 System
.Console
.WriteLine ("Delayed query fired");
432 private void QueueDelayedQuery (string query
)
434 delayedQuery
= query
;
435 GLib
.Timeout
.Add (10000, new GLib
.TimeoutHandler (RunDelayedQuery
));
438 private void DoSearch (object o
, EventArgs args
)
440 if (entry
.GtkEntry
.Text
!= null && entry
.GtkEntry
.Text
!= "")
441 Search (entry
.GtkEntry
.Text
);
444 //private string lastType = null;
446 private void ChangeType (object o
, EventArgs args
)
448 Gtk
.OptionMenu opt
= (Gtk
.OptionMenu
) o
;
449 TypeMenuItem mi
= (TypeMenuItem
) this.menu_items
[opt
.History
];
451 if (this.hit_type
== mi
.Type
)
454 this.hit_type
= mi
.Type
;
456 root
.SetSource (this.hit_type
);
457 root
.HitCollection
.PageFirst ();
460 //if (this.query != null && lastType != this.hit_type) {
461 // Search (entry.GtkEntry.Text);
462 // lastType = this.hit_type;
467 //////////////////////////
469 private void OnHitsAdded (HitsAddedResponse response
)
471 root
.Add (response
.Hits
);
475 private void OnHitsSubtracted (HitsSubtractedResponse response
)
477 root
.Subtract (response
.Uris
);
481 private void OnFinished (FinishedResponse repsonse
)
486 private void OnCancelled (CancelledResponse response
)
491 private void AttachQuery ()
493 query
.HitsAddedEvent
+= OnHitsAdded
;
494 query
.HitsSubtractedEvent
+= OnHitsSubtracted
;
495 query
.FinishedEvent
+= OnFinished
;
496 query
.CancelledEvent
+= OnCancelled
;
499 private void DetachQuery ()
502 query
.HitsAddedEvent
-= OnHitsAdded
;
503 query
.HitsSubtractedEvent
-= OnHitsSubtracted
;
504 query
.FinishedEvent
-= OnFinished
;
505 query
.CancelledEvent
-= OnCancelled
;
512 private void StartQuery ()
517 } catch (Beagle
.ResponseMessageException e
) {
518 QueueDelayedQuery (entry
.GtkEntry
.Text
);
520 /* To translators: {0} represents the current query keywords */
521 root
.Error (String
.Format (Catalog
.GetString ("The query for <i>{0}</i> failed." +
522 "<br>The likely cause is that the beagle daemon isn't running."), entry
.GtkEntry
.Text
));
523 root
.OfferDaemonRestart
= true;
524 } catch (Exception e
) {
525 /* To translators: {0} represents the current query keywords, {1} contains the errormessage */
526 root
.Error (String
.Format (Catalog
.GetString ("The query for <i>{0}</i> failed with error:<br>{1}<br>"),
527 entry
.GtkEntry
.Text
, e
));
531 private void Search (String searchString
)
533 StoreSearch (searchString
);
534 entry
.GtkEntry
.Text
= searchString
;
537 try { DetachQuery (); }
catch (ObjectDisposedException e
) {}
540 query
= new Query ();
541 query
.AddDomain (QueryDomain
.Neighborhood
);
543 // FIXME: Disable non-local searching for now.
544 //query.AddDomain (QueryDomain.Global);
546 query
.AddText (searchString
);
547 root
.SetSource (hit_type
);
559 ArrayList recentSearches
;
561 private void StoreSearch (string newQuery
)
563 if (recentSearches
== null) {
564 recentSearches
= new ArrayList ();
567 if (newQuery
!= null && newQuery
!= "") {
568 int duplicate
= recentSearches
.IndexOf (newQuery
);
569 if (duplicate
>= 0) {
570 recentSearches
.RemoveAt (duplicate
);
572 recentSearches
.Insert (0, newQuery
);
575 if (recentSearches
.Count
== 11) {
576 recentSearches
.RemoveAt (10);
580 public ArrayList
RetriveSearches ()
582 return recentSearches
;
585 public void ClearHistory ()
587 entry
.ClearHistory ();
588 recentSearches
.Clear ();
591 public void QuickSearch (string query
)