[banshee] [Banshee.ThickClient] Add g keybinding to switch sources



commit 451456396c78900222cfa6b3722e923f3632e953
Author: Gabriel Burt <gabriel burt gmail com>
Date:   Sat Apr 3 18:36:42 2010 -0700

    [Banshee.ThickClient] Add g keybinding to switch sources
    
    Implements bgo#614766, adding global 'g' keybinding that pops up
    type-ahead-find like entry, where you can type a source name, part of
    it, or even its initials, press enter, and the active source will be
    changed.

 .../Banshee.Gui/SourceActions.cs                   |   93 ++++++++++++++++++++
 .../Resources/core-ui-actions-layout.xml           |    1 +
 2 files changed, 94 insertions(+), 0 deletions(-)
---
diff --git a/src/Core/Banshee.ThickClient/Banshee.Gui/SourceActions.cs b/src/Core/Banshee.ThickClient/Banshee.Gui/SourceActions.cs
index 4af7a7d..3e956d1 100644
--- a/src/Core/Banshee.ThickClient/Banshee.Gui/SourceActions.cs
+++ b/src/Core/Banshee.ThickClient/Banshee.Gui/SourceActions.cs
@@ -27,6 +27,8 @@
 //
 
 using System;
+using System.Linq;
+using System.Collections.Generic;
 using Mono.Unix;
 using Gtk;
 
@@ -105,6 +107,11 @@ namespace Banshee.Gui
                     Catalog.GetString ("Sort Children by"), null, null,
                     OnSortChildrenMenu),
 
+                new ActionEntry ("OpenSourceSwitcher", null,
+                    Catalog.GetString ("Switch Source"), "G",
+                    Catalog.GetString ("Switch to a source by typing its name"),
+                    OnOpenSourceSwitcher),
+
                 new ActionEntry ("SourcePreferencesAction", null, Catalog.GetString ("Preferences"), null,
                     Catalog.GetString ("Edit preferences related to this source"), OnSourcePreferences),
 
@@ -334,6 +341,92 @@ namespace Banshee.Gui
             }
         }
 
+        private void OnOpenSourceSwitcher (object o, EventArgs args)
+        {
+            var popup = new Hyena.Widgets.EntryPopup ();
+
+            // FIXME not sure if it's possible to do auto-complete w/o a Model
+            /*var completion = new EntryCompletion () {
+                InlineSelection = true,
+                InlineCompletion = true,
+                PopupCompletion = true,
+                PopupSingleMatch = true,
+                MinimumKeyLength = 2
+            };
+
+            popup.Entry.Completion = completion;
+            completion.ActionActivated += (o2, a) => {
+                try {
+                    var src = SourceSwitcherMatches (popup.Text).Skip (a.Index).FirstOrDefault ();
+                    if (src != null) {
+                        ServiceManager.SourceManager.SetActiveSource (src);
+                    }
+                } catch {}
+            };
+
+            popup.Changed += delegate {
+                completion.Clear ();
+                completion.Complete ();
+
+                int i = 0;
+                foreach (var src in SourceSwitcherMatches (popup.Text)) {
+                    completion.InsertActionText (i++, src.Name);
+                }
+            };*/
+
+            popup.Entry.Activated += delegate {
+                try {
+                    var src = SourceSwitcherMatches (popup.Text).FirstOrDefault ();
+                    if (src != null) {
+                        ServiceManager.SourceManager.SetActiveSource (src);
+                    }
+                } catch {}
+            };
+
+            var label = new Label (Catalog.GetString ("Switch to source:")) { Visible = true };
+            popup.Box.PackStart (label, false, false, 0);
+            popup.Box.ReorderChild (label, 0);
+
+            popup.Position (ServiceManager.Get<GtkElementsService> ().PrimaryWindow.GdkWindow);
+            popup.HasFocus = true;
+            popup.Show ();
+        }
+
+        private IEnumerable<Source> SourceSwitcherMatches (string query)
+        {
+            query = StringUtil.SearchKey (query);
+            if (String.IsNullOrEmpty (query)) {
+                return Enumerable.Empty<Source> ();
+            }
+
+            return ServiceManager.SourceManager.Sources
+                                               .Select  (s => new { Source = s, Priority = SourceSwitcherPriority (s, query) })
+                                               .Where   (s => s.Priority > 0)
+                                               .OrderBy (s => s.Priority)
+                                               .Select  (s => s.Source);
+        }
+
+        private int SourceSwitcherPriority (Source s, string query)
+        {
+            int priority = 0;
+            var name = StringUtil.SearchKey (s.Name);
+            if (name != null) {
+                if (name.StartsWith (query)) {
+                    priority = 1;
+                } else {
+                    var split_name = name.Split (' ');
+                    if (split_name.Length == query.Length &&
+                        Enumerable.Range (0, query.Length).All (i => split_name[i][0] == query[i])) {
+                        priority = 2;
+                    } else if (name.Contains (query)) {
+                        priority = 3;
+                    }
+                }
+            }
+
+            return priority;
+        }
+
         private void OnSourcePreferences (object o, EventArgs args)
         {
             try {
diff --git a/src/Core/Banshee.ThickClient/Resources/core-ui-actions-layout.xml b/src/Core/Banshee.ThickClient/Resources/core-ui-actions-layout.xml
index e6843e5..b155bff 100644
--- a/src/Core/Banshee.ThickClient/Resources/core-ui-actions-layout.xml
+++ b/src/Core/Banshee.ThickClient/Resources/core-ui-actions-layout.xml
@@ -46,6 +46,7 @@
       <menuitem name="Import" action="ImportAction"/>
       <menuitem name="ImportPlaylist" action="ImportPlaylistAction"/>
       <menuitem name="OpenLocation" action="OpenLocationAction"/>
+      <menuitem action="OpenSourceSwitcher"/>
       <separator/>
       <placeholder name="BelowOpenLocation"/>
       <separator/>



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]