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
;
43 public class TypeMenuItem
: Gtk
.MenuItem
{
47 public TypeMenuItem (string label
, string type
) : base (label
)
53 public class BestWindow
: Gtk
.Window
{
55 Gtk
.AccelGroup accel_group
;
56 GlobalKeybinder global_keys
;
58 public BestWindow (string query
) : base (WindowType
.Toplevel
)
63 public BestWindow () : base (WindowType
.Toplevel
)
68 public void FocusEntry ()
73 public void FocusEntryHandler (object o
, EventArgs args
)
78 private void CreateWindow (string query
)
80 Title
= Best
.DefaultWindowTitle
;
82 DeleteEvent
+= new DeleteEventHandler (this.DoDelete
);
83 MapEvent
+= new MapEventHandler (MapIt
);
84 UnmapEvent
+= new UnmapEventHandler (UnmapIt
);
86 Icon
= Images
.GetPixbuf ("best.png");
88 Widget content
= CreateContents ();
90 VBox main
= new VBox (false, 3);
91 main
.PackStart (content
, true, true, 3);
98 root
= new SimpleRootTile ();
104 accel_group
= new Gtk
.AccelGroup ();
105 this.AddAccelGroup (accel_group
);
106 global_keys
= new GlobalKeybinder (accel_group
);
108 // Close window (Ctrl-W)
109 global_keys
.AddAccelerator (new EventHandler (this.HideWindowHandler
),
111 Gdk
.ModifierType
.ControlMask
,
112 Gtk
.AccelFlags
.Visible
);
114 // Close window (Escape)
115 global_keys
.AddAccelerator (new EventHandler (this.HideWindowHandler
),
116 (uint) Gdk
.Key
.Escape
,
118 Gtk
.AccelFlags
.Visible
);
120 // Show source (Ctrl+U)
121 global_keys
.AddAccelerator (new EventHandler (this.ShowSource
),
123 Gdk
.ModifierType
.ControlMask
,
124 Gtk
.AccelFlags
.Visible
);
126 // Focus Entry (Ctrl+L)
127 global_keys
.AddAccelerator (new EventHandler (this.FocusEntryHandler
),
129 Gdk
.ModifierType
.ControlMask
,
130 Gtk
.AccelFlags
.Visible
);
132 // Previous Page (PageUp)
133 global_keys
.AddAccelerator (new EventHandler (this.PageBackHandler
),
134 (uint) Gdk
.Key
.Page_Up
,
136 Gtk
.AccelFlags
.Visible
);
138 // Next Page (PageDown)
139 global_keys
.AddAccelerator (new EventHandler (this.PageForwardHandler
),
140 (uint) Gdk
.Key
.Page_Down
,
142 Gtk
.AccelFlags
.Visible
);
152 //////////////////////////
154 int posX
= 0, posY
= 0;
156 public new void Present ()
163 public new void Hide ()
165 // FIXME: Hack, why does Hide () gets invoked twice, the second time with (0,0) as window position?
167 int new_posX
= 0, new_posY
= 0;
169 GetPosition (out new_posX
, out new_posY
);
171 if (new_posX
!= 0 && new_posY
!= 0) {
179 //////////////////////////
182 string hit_type
= null;
184 private void SetBusy (bool busy
)
187 this.GdkWindow
.Cursor
= new Gdk
.Cursor (Gdk
.CursorType
.Watch
);
189 this.GdkWindow
.Cursor
= null;
194 private void DoDelete (object o
, DeleteEventArgs args
)
199 public bool WindowIsVisible
;
201 private void MapIt (object o
, MapEventArgs args
)
203 WindowIsVisible
= true;
206 private void UnmapIt (object o
, UnmapEventArgs args
)
208 WindowIsVisible
= false;
211 private void HideWindowHandler (object o
, EventArgs args
)
216 private void ShowSource (object o
, EventArgs args
)
218 Gtk
.Window win
= new Gtk
.Window ("Source");
219 win
.SetDefaultSize (800,500);
220 Gtk
.ScrolledWindow sw
= new ScrolledWindow ();
221 sw
.HscrollbarPolicy
= Gtk
.PolicyType
.Automatic
;
222 sw
.VscrollbarPolicy
= Gtk
.PolicyType
.Automatic
;
223 Gtk
.TextView view
= new Gtk
.TextView ();
224 view
.CursorVisible
= false;
225 view
.Editable
= false;
226 Gtk
.TextBuffer buffer
= view
.Buffer
;
227 buffer
.Text
= canvas
.Source
;
228 view
.Buffer
= buffer
;
234 //////////////////////////
236 private void PageForward ()
238 if (!root
.HitCollection
.CanPageForward
)
241 root
.HitCollection
.PageForward ();
245 private void PageBack ()
247 if (!root
.HitCollection
.CanPageBack
)
250 root
.HitCollection
.PageBack ();
254 private void PageForwardHandler (object o
, EventArgs args
)
259 private void PageBackHandler (object o
, EventArgs args
)
264 //////////////////////////
266 private Gtk
.Entry entry
;
267 private Gtk
.ListStore history
;
269 private Gtk
.ListStore filter_data
;
271 private TileCanvas canvas
;
272 private SimpleRootTile root
;
273 private Gtk
.Label page_label
;
274 private Gtk
.Button back_button
;
275 private Gtk
.Button forward_button
;
277 private Gtk
.Button
StockButton (string stockid
, string label
)
279 Gtk
.HBox button_contents
= new HBox (false, 0);
280 button_contents
.Show ();
281 Gtk
.Widget button_image
= new Gtk
.Image (stockid
, Gtk
.IconSize
.Button
);
282 button_image
.Show ();
283 button_contents
.PackStart (button_image
, false, false, 1);
284 Gtk
.Label button_label
= new Gtk
.Label (label
);
285 button_label
.Show ();
286 button_contents
.PackStart (button_label
, false, false, 1);
288 Gtk
.Button button
= new Gtk
.Button ();
289 button
.Add (button_contents
);
294 private Gtk
.ComboBox
FilterComboBox ()
296 filter_data
= new Gtk
.ListStore (new Type
[] { typeof (string), typeof (string) }
);
300 iter
= filter_data
.Append ();
301 filter_data
.SetValue (iter
, 0, Catalog
.GetString ("Anywhere"));
302 filter_data
.SetValue (iter
, 1, null);
304 iter
= filter_data
.Append ();
305 filter_data
.SetValue (iter
, 0, Catalog
.GetString ("in Files"));
306 filter_data
.SetValue (iter
, 1, "File");
308 iter
= filter_data
.Append ();
309 filter_data
.SetValue (iter
, 0, Catalog
.GetString ("in Addressbook"));
310 filter_data
.SetValue (iter
, 1, "Contact");
312 iter
= filter_data
.Append ();
313 filter_data
.SetValue (iter
, 0, Catalog
.GetString ("in Mail"));
314 filter_data
.SetValue (iter
, 1, "MailMessage");
316 iter
= filter_data
.Append ();
317 filter_data
.SetValue (iter
, 0, Catalog
.GetString ("in Web Pages"));
318 filter_data
.SetValue (iter
, 1, "WebHistory");
320 iter
= filter_data
.Append ();
321 filter_data
.SetValue (iter
, 0, Catalog
.GetString ("in Chats"));
322 filter_data
.SetValue (iter
, 1, "IMLog");
324 Gtk
.ComboBox combo
= new Gtk
.ComboBox (filter_data
);
327 Gtk
.CellRendererText renderer
= new Gtk
.CellRendererText ();
328 combo
.PackStart (renderer
, false);
329 combo
.SetAttributes (renderer
, new object[] { "text", 0 }
);
334 private Gtk
.Widget
CreateContents ()
336 Gtk
.HBox entryLine
= new HBox (false, 4);
338 Gtk
.Label words
= new Gtk
.Label (Catalog
.GetString ("Search terms:"));
339 entryLine
.PackStart (words
, false, false, 3);
341 history
= new Gtk
.ListStore (new Type
[] { typeof (string) }
);
343 Gtk
.EntryCompletion comp
= new Gtk
.EntryCompletion ();
344 comp
.Model
= history
;
347 entry
= new Gtk
.Entry ("");
348 entry
.Activated
+= new EventHandler (this.DoSearch
);
349 entry
.Completion
= comp
;
350 entryLine
.PackStart (entry
, true, true, 3);
352 words
= new Gtk
.Label ("");
353 entryLine
.PackStart (words
, false, false, 3);
355 Gtk
.ComboBox combo
= FilterComboBox ();
356 combo
.Changed
+= new EventHandler (this.ChangeType
);
357 entryLine
.PackStart (combo
, false, false, 3);
359 Gtk
.HBox buttonContents
= new HBox (false, 0);
360 Gtk
.Widget buttonImg
= Beagle
.Images
.GetWidget ("icon-search.png");
361 buttonContents
.PackStart (buttonImg
, false, false, 1);
362 Gtk
.Label buttonLabel
= new Gtk
.Label (Catalog
.GetString ("Find"));
363 buttonContents
.PackStart (buttonLabel
, false, false, 1);
365 Gtk
.Button button
= new Gtk
.Button ();
366 button
.Add (buttonContents
);
367 button
.Clicked
+= new EventHandler (this.DoSearch
);
368 entryLine
.PackStart (button
, false, false, 3);
370 Gtk
.Button clearButton
= new Gtk
.Button ();
371 clearButton
.Label
= "Clear";
372 clearButton
.Clicked
+= new EventHandler (this.ClearSearch
);
373 entryLine
.PackStart (clearButton
, false, false, 4);
375 canvas
= new TileCanvas ();
378 HBox pager
= new HBox ();
379 page_label
= new Label ();
381 pager
.PackStart (page_label
, false, false, 3);
383 forward_button
= StockButton ("gtk-go-forward",
384 Catalog
.GetString ("Show More Results"));
385 forward_button
.Show ();
386 forward_button
.Clicked
+= new EventHandler (PageForwardHandler
);
387 pager
.PackEnd (forward_button
, false, false, 3);
389 back_button
= StockButton ("gtk-go-back",
390 Catalog
.GetString ("Show Previous Results"));
393 back_button
.Clicked
+= new EventHandler (PageBackHandler
);
394 pager
.PackEnd (back_button
, false, false, 3);
398 VBox contents
= new VBox (false, 3);
399 contents
.PackStart (entryLine
, false, true, 3);
400 contents
.PackStart (canvas
, true, true, 3);
401 contents
.PackStart (pager
, false, false, 3);
403 entryLine
.ShowAll ();
409 private void UpdateFromConf ()
411 Console
.WriteLine ("Reading settings from Config");
412 // FIXME: there might be weird cases with multiple screens,
413 // multiple monitors, resolution related problems that might
414 // cause problem is remapping the stored values to current
415 // screen coordinates
416 int res_x
= GD
.Screen
.Default
.Width
;
417 int res_y
= GD
.Screen
.Default
.Height
;
418 int pos_x
= (int)(Conf
.Searching
.BestPosX
* res_x
/ 100);
419 int pos_y
= (int)(Conf
.Searching
.BestPosY
* res_y
/ 100);
420 int width
= (int)(Conf
.Searching
.BestWidth
* res_x
/ 100 );
421 int height
= (int)(Conf
.Searching
.BestHeight
* res_y
/ 100);
423 if (pos_x
!= 0 || pos_y
!= 0) {
429 DefaultWidth
= width
;
431 DefaultHeight
= height
;
433 foreach (string search
in Conf
.Searching
.SearchHistory
) {
434 iter
= history
.Append ();
435 history
.SetValue (iter
, 0, search
);
439 public void StoreSettingsInConf (bool with_tray
)
441 Console
.WriteLine ("Storing setting in Config");
442 int pos_x
= posX
, pos_y
= posY
;
443 if (with_tray
&& WindowIsVisible
)
444 GetPosition (out pos_x
, out pos_y
);
445 int width
= 0, height
= 0;
446 GetSize (out width
, out height
);
448 int res_x
= GD
.Screen
.Default
.Width
;
449 int res_y
= GD
.Screen
.Default
.Height
;
450 Conf
.Searching
.BestPosX
= ((float) pos_x
/ res_x
) * 100;
451 Conf
.Searching
.BestPosY
= ((float) pos_y
/ res_y
) * 100;
452 Conf
.Searching
.BestWidth
= ((float) width
/ res_x
) * 100;
453 Conf
.Searching
.BestHeight
= ((float) height
/ res_y
) * 100;
454 Conf
.Searching
.SearchHistory
= RetriveSearches ();
455 Conf
.Searching
.SaveNeeded
= true;
459 private void UpdatePage ()
461 //Console.WriteLine ("In UpdatePage");
462 back_button
.Sensitive
= root
.HitCollection
.CanPageBack
;
463 forward_button
.Sensitive
= root
.HitCollection
.CanPageForward
;
468 if (this.hit_type
== null)
469 results
= root
.HitCollection
.NumResults
;
471 results
= root
.HitCollection
.NumDisplayableResults
;
474 label
= Catalog
.GetString ("No results.");
475 } else if (root
.HitCollection
.FirstDisplayed
== 0) {
476 /* To translators: {0} is the current count of results shown of {1} in total, this is the message that is initially shown */
477 /* when results are returned to the user. */
478 label
= String
.Format (Catalog
.GetString ("Best <b>{0} results of {1}</b> are shown."),
479 root
.HitCollection
.LastDisplayed
+ 1,
482 /* To translators: {0} to {1} is the interval of results currently shown of {2} results in total*/
483 label
= String
.Format (Catalog
.GetString ("Results <b>{0} through {1} of {2}</b> are shown."),
484 root
.HitCollection
.FirstDisplayed
+ 1,
485 root
.HitCollection
.LastDisplayed
+ 1,
488 page_label
.Markup
= label
;
491 private string delayedQuery
= null;
493 private bool RunDelayedQuery ()
495 if (delayedQuery
!= null) {
497 System
.Console
.WriteLine ("Delayed query fired");
504 private void QueueDelayedQuery (string query
)
506 delayedQuery
= query
;
507 GLib
.Timeout
.Add (10000, new GLib
.TimeoutHandler (RunDelayedQuery
));
510 private void DoSearch (object o
, EventArgs args
)
512 if (entry
.Text
!= null && entry
.Text
!= "")
516 //private string lastType = null;
518 private void ChangeType (object o
, EventArgs args
)
520 Gtk
.ComboBox combo
= (Gtk
.ComboBox
) o
;
521 string hit_type
= null;
524 if (combo
.GetActiveIter (out iter
))
525 hit_type
= (string) filter_data
.GetValue (iter
, 1);
527 if (this.hit_type
== hit_type
)
530 this.hit_type
= hit_type
;
532 root
.SetSource (this.hit_type
);
533 root
.HitCollection
.PageFirst ();
537 //////////////////////////
539 private void OnHitsAdded (HitsAddedResponse response
)
541 root
.Add (response
.Hits
);
545 private void OnHitsSubtracted (HitsSubtractedResponse response
)
547 root
.Subtract (response
.Uris
);
551 private void OnFinished (FinishedResponse repsonse
)
556 private void AttachQuery ()
558 query
.HitsAddedEvent
+= OnHitsAdded
;
559 query
.HitsSubtractedEvent
+= OnHitsSubtracted
;
560 query
.FinishedEvent
+= OnFinished
;
563 private void DetachQuery ()
566 query
.HitsAddedEvent
-= OnHitsAdded
;
567 query
.HitsSubtractedEvent
-= OnHitsSubtracted
;
568 query
.FinishedEvent
-= OnFinished
;
575 private void StartQuery ()
580 } catch (Beagle
.ResponseMessageException e
) {
581 QueueDelayedQuery (entry
.Text
);
583 /* To translators: {0} represents the current query keywords */
584 root
.Error (String
.Format (Catalog
.GetString ("The query for <i>{0}</i> failed." +
585 "<br>The likely cause is that the beagle daemon isn't running."), entry
.Text
));
586 root
.OfferDaemonRestart
= true;
587 } catch (Exception e
) {
588 /* To translators: {0} represents the current query keywords, {1} contains the errormessage */
589 root
.Error (String
.Format (Catalog
.GetString ("The query for <i>{0}</i> failed with error:<br>{1}<br>"),
594 private void Search (String searchString
)
596 entry
.Text
= searchString
;
597 StoreSearch (searchString
);
600 try { DetachQuery (); }
catch (ObjectDisposedException e
) {}
603 query
= new Query ();
604 query
.AddDomain (QueryDomain
.Neighborhood
);
606 // FIXME: Disable non-local searching for now.
607 //query.AddDomain (QueryDomain.Global);
609 query
.AddText (searchString
);
610 root
.SetSource (hit_type
);
622 private void ClearSearch (object o
, EventArgs args
)
627 // clear search is also "stop current search" - implicitly
631 private void StoreSearch (string query
)
635 if (history
.GetIterFirst (out iter
)) {
639 val
= (string) history
.GetValue (iter
, 0);
642 history
.Remove (ref iter
);
643 } while (val
!= query
&& history
.IterNext (ref iter
));
646 iter
= history
.Insert (0);
647 history
.SetValue (iter
, 0, query
);
650 public ArrayList
RetriveSearches ()
652 ArrayList searches
= new ArrayList ();
655 foreach (object[] o
in history
) {
666 public void ClearHistory ()
671 public void QuickSearch (string query
)