GNOME Bugzilla – Bug 399655
Jump to song starting with 'foo' (GTK+ type-ahead search)
Last modified: 2015-07-09 15:11:23 UTC
Would be handy for long playlists/librarys to jump straight to artist name simply by entering the information, similar to nautilus. if this was implimented the 'fwd' and 'prev' key shortcuts would need to be changed. Other information: Search is not convinient for this as it limits whats displayed to a certain value. I'm suggesting a quick 'jump-to' by first letters of the artist name by typing at any time..
This is an enhancement.
I'd also suggest that this not start playing when it jumps. That could get really annoying if I fat finger something, who knows where I'd end up.
If we implement this at all, I'd suggest making it look like Gtk.TreeView's built-in search box (eg bottom right), and it could only search the column that is sorted (or should it search the default columns, title, album, artist?)
*** Bug 507665 has been marked as a duplicate of this bug. ***
See bug #507665 for a lot more discussion.
*** Bug 536295 has been marked as a duplicate of this bug. ***
*** Bug 537994 has been marked as a duplicate of this bug. ***
(In reply to comment #1) > This is an enhancement. I know Banshee is using a custom widget, but why isn't this a normal/minor bug?
Because even with a Gtk.TreeView you'd have to turn on the type-ahead-find and configure it, possibly even writing your own match function. There's nothing wrong with the current behavior, so it's not a bug.
Interestingly enough though, when you click on an item in the left side navigation, like "Now Playing" and start typing, the "find" box pops up but it doesn't actually find anything. It seems like if it's going to use the "find" box instead of Banshee's custom widget, it might as well actually find something. ...although I'd much prefer this feature being built into the music library instead of just the left navigation menu.
*** Bug 551598 has been marked as a duplicate of this bug. ***
*** Bug 553317 has been marked as a duplicate of this bug. ***
*** Bug 557968 has been marked as a duplicate of this bug. ***
Does this bug include the idea of using type-ahead find in the artist/album browsers?
Yes, since they're the same widget and the idea IMO makes as much sense (or more) for them than is does for tracks.
I would really like this to work in the artist/album browser windows. This missing feature has kept me switching back and forth between Banshee and Rhythmbox. It takes less effort to skip to the artist or album that you may want then it takes to use the search; which hides everything else, then makes you clear the search box to see everything else again. This kind of "skipping" works in iTunes, Rhythmbox, Songbird and many others.. I don't know why Banshee shouldn't have it, but I can see why it could be useful in Banshee.
I was going to report this as an enhancement myself before I found this. This one small feature would make Banshee so much better. It's the one thing that gets really annoying and all other music players I've used follow this behaviour. If I have my artist or library list in focus and I type "n" I want to go to the artists beginning with n, I don't want to play the next song. Yes this would require changing the shortcuts, but I think that's acceptable as this is the behaviour many new users would expect. Most other applications also require pressing "Ctrl" or "Alt" in combination with shortcut keys.
Agreed. This is the one thing keeping me from using Banshee fulltime. I'm not a fan of the default shortcuts (which get on the way of type-ahead search) but if they are set in stone, then why not give an option to activate type-ahead search? As it is, Banshee breaks with the expected Gtk/Gnome behavior and makes everyone I know change my song queue by accident when trying to search :) What are the main obstacles for this? I know a treeview widget has been created from the ground up, and that this probably requires some extra coding, but are there any technical reasons why this has not been implemented?
I agree, this is the one feature that I would like to see more than anything else, and the one major deal-breaker keeping me from using banshee as my main media-player. Almost everything else (Nautilus, all the other media players I have used, windows explorer, etc) has type-ahead functionality, and many people. myself included, have grown used to it and expect it. I consider it a bug, in that it is a feature I took for granted, but it wasn't working (due to the fact that it was missing, of course). The search function is nice, but not nearly as handy, -- I can't just jump to an artist. If it type the artist name in the box, I don't see anythign OTHER than that artist (or even other songs with the name of that artist that I was not looking for). I often try to use it without thinking about it, and accidently press one of the shortcuts, which is bothersome. I would be interested to know if/when this might appear in a future release, and what might be necessary to get it working. Thanks.
*** Bug 588912 has been marked as a duplicate of this bug. ***
Created attachment 147152 [details] [review] First iteration Attached is a partially working patch. My goal was to closely model the behaviour of Rhythmbox. I chose to implement this as a subclass of ListView called SearchableListView. AlbumInfo, ArtistInfo, and TrackInfo implement a new interface called ISearchable. They all define a new method called Find that takes a target string and returns a bool value to indicate a hit or miss. Known issues remaining: * Popup behaviour is close, but not perfect ie. when Application window is moved pop-up should disappear, etc. FocusOut event is not getting raised. I'm guessing because the popup is modal? * Handling of keyboard shortcuts already in place ie. should ListView popup be brought up with some other key combination to preserve existing shortcuts? * SearchableListView.PerformSearch method ie. is this sufficient? Zippy with my 2500 track library, but maybe not with larger libraries. It's currently performing a sequential search. A more efficient implementation might restrict searching to the sorted column of the ListView and perform a binary search? Not sure if that is necessary, however. Feedback, especially on the implementation decisions, would be awesome before doing anything further
(In reply to comment #21) > Created an attachment (id=147152) [details] [review] > First iteration > > Attached is a partially working patch. My goal was to closely model the > behaviour of Rhythmbox. First of all, you are awesome for working on this. Once I have a little free time, I'm definitely looking forward to testing the patch. How closely does this model Rhythmbox's behavior? If I remember correctly, Rhythmbox searches any word in the title. I prefer searching the Artist column instead, but that's definitely my past iTunes experience speaking. > * Handling of keyboard shortcuts already in place ie. should ListView popup be > brought up with some other key combination to preserve existing shortcuts? I have a feeling that Banshee developers will be in favor of preserving the existing shortcuts, but before they chime in, I'd like to make the case for replacing the existing shortcuts. The existing shortcuts are hard to discover and not well documented. Some of these shortcuts (N, B, T, F, R) can be found in the menus. Others (o, /, y) can be found in the support section of Banshee's website. I couldn't find the "S" shortcut (focus on the search field) mentioned anywhere. Many of the existing shortcuts are duplicates of other keyboard shortcuts. S and / both duplicate Ctrl+F for focusing on the search box (and searching will hopefully be less common once type-ahead is implemented). F does the same thing as F11, and F11 is more common in other applications. Restart is basically a duplicate of Previous (Bug 576931), so R essentially duplicates B. If Bug 535924 is fixed, N and B won't be necessary because Control-Right and Control Left (or some variation) will do the same thing. Also, type-ahead should be a quick way of navigating a collection. Requiring an extra keystroke to trigger it defeats (some of) the purpose. If you need to use an extra key to do the search, you might as well hit the "/" or "s" key and just use the search box. Users familiar with this kind of searching in Rhythmbox, Nautilus, and Firefox (to name only a few) won't expect an extra key to trigger type-ahead. The lost keyboard shortcuts could probably add a Ctrl modifier, or maybe choosing between type-ahead and Banshee's current keyboard shortcuts could be a preferences option somewhere. If it's all-or-nothing, though, I'd really like to throw in my vote for type-ahead replacing shortcuts.
(In reply to comment #22) > How closely does this model Rhythmbox's behavior? If I remember correctly, > Rhythmbox searches any word in the title. I prefer searching the Artist column > instead, but that's definitely my past iTunes experience speaking. > This is one area where my implementation differs. When typing ahead on the track list the track name, artist name, and album name are searched in that order. And, it's currently not searching for any word. That's an oversight on my part. Currently, it takes the type ahead string and looks for a match in one of the above columns that start with it. This can easily be changed.
Created attachment 147189 [details] [review] 2nd iteration * Allow up / down key use when jump ahead popup is in use. This lets the user move to the next / previous search result * Use String.Contains instead of String.StartsWith for matching
(In reply to comment #24) > * Use String.Contains instead of String.StartsWith for matching Just a note: iTunes only compares the typed string with the start, not if it is contained within the text. And if it has no results, it lands at the closest match (type "Mon" and you land on the first "Morcheba", after "Moby").
(In reply to comment #24) > * Use String.Contains instead of String.StartsWith for matching I actually think that StartsWith is a better choice than Contains for a type-ahead search. If you're searching for "contains" in 3 different columns in a decently large library, the chances of actually hitting what you're looking for when you start typing seems fairly low. Of course I have no data to back this up, but I did come up with one lame scenario: I want to listen to a song that's name begins with "in the". With my library, typing "in the" would have a 1/130 chance of hitting the song I want using the Contains method and a 1/8 chance using StartsWith. Since speed of navigation is one major advantage of type-ahead, I think enforcing a more strict searching policy (eg "you have to start searching with the beginning of the track/artist/album name") is a fair compromise for returning more relevant results more quickly. If the user wants a more complete list of matches, there's always standard slow searching for that. Of course, this is just my 2 cents (for the second time today; I guess we're almost up to a nickel...). I haven't even tested the patch yet, but I will in just a minute.
Thanks for working on this Neil. I'd be much more comfortable if the lookup happened in the Model, not by iterating the list. That way we can implement a SQL-based lookup for all DatabaseSources, using a combination of the existing query infrastructure (QueryFields + '=' operator) and adding a new IndexOf method that takes the query and an offset # and uses its cache to look it up.
Created attachment 147451 [details] [review] 3rd iteration Thanks for the feedback, Gabriel. I've changed the ISearchable interface so it applies to the model instead. It enforces a DefaultQueryFields property definition, so the SearchableListView knows which fields it can search. And, it also enforces an IndexOf method implementation. The IndexOf method in the model takes a QueryNode as a parameter. Not sure if maybe that is too strict and a string representing a SQL WHERE fragment would be better? Comments on what I've done would be great. I think this is a step in the right direction, as searching large libraries should no longer be an issue.
Review of attachment 147451 [details] [review]: Great job Neil, I think this is definitely on the right track. I think passing the QueryNode in IndexOf makes perfect sense - not all models will be SQL backed, and they can deal w/ the QueryNode tree how they want. ::: src/Core/Banshee.Services/Banshee.Collection.Database/DatabaseAlbumListModel.cs @@ +48,3 @@ source, trackModel, connection, DatabaseAlbumInfo.Provider, new AlbumInfo (null), uuid) { + DefaultQueryFields = new QueryField[] { Banshee.Query.BansheeQuery.AlbumField }; Hrm, not seeing it in HACKING, but I think we usually put a space before [] in array ctor calls. ::: src/Core/Banshee.Services/Banshee.Collection.Database/DatabaseFilterListModel.cs @@ +234,3 @@ + } + + long index = cache.IndexOf (query.ToSql (null), offset); I think it's crucial to pass the QueryFieldSet to ToSql - it's used to determine the default fields if there is a QueryTermNode that doesn't specify a field. In fact, instead of having the DefaultQueryFields property on ISearchable, should probably just have a QueryFieldSet, which is basically the same thing. Then for the track model, you can just reuse BansheeQuery.FieldSet. Note that QueryFieldSet class is a list of fields, with some of them marked as Default fields, such that if a QueryTermNode doesn't specify a column, it'll search all of them. ::: src/Core/Banshee.Services/Banshee.Collection.Database/ISearchable.cs @@ +34,3 @@ + public interface ISearchable + { + QueryField[] DefaultQueryFields { get; set; } Don't need setter in the iface ::: src/Core/Banshee.ThickClient/Banshee.Collection.Gui/SearchableListView.cs @@ +58,3 @@ + } + + //TODO building tree on every search is probably unnecessary To avoid this, can cache the QueryListNode and the last target, and reuse if target is the same. @@ +150,3 @@ + // this is exactly what the base class does + // perhaps just make change from private to protected there? + protected void InvalidateList () Making this protected in ListView is fine with me ::: src/Libraries/Hyena.Gui/Hyena.Widgets/EntryPopup.cs @@ +63,3 @@ + text_entry.CanFocus = true; + + text_entry.FocusOutEvent += delegate(object o, FocusOutEventArgs args) { instead of all these delegates, use += (o, a) => ::: src/Libraries/Hyena/Hyena.Data.Sqlite/SqliteModelCache.cs @@ +242,3 @@ + } + + String sql = String.Format (select_str + " {0} LIMIT {1}, 1", where_fragment, offset); instead of concatenating select_str here, can just add it to the string.format also, String sql -> string sql (we use keyword names of value types for var declarations)
Created attachment 147607 [details] [review] 4th iteration Applied your comments, Gabriel. Other notable stuff in this patch: * To build the query tree, SearchableListView will pick out the default fields in the QueryFieldSet it finds in its model. If none of the fields are defaults, it will take all of them. * DatabaseQueryFilterModel updated to allow searching (ie. the Genre browser for the Radio extension). SqlliteModelCache required some tweaking. * No longer calling Provider.Load in the new SqlliteModelCache.IndexOf method. It's unnecessary. I've noticed that the search popup for the SourceView, which is a subclass of TreeView, behaves exactly (from my observations) like my new EntryPopup widget. For example, when the main window is moved, the popup stays open. So, I'm wondering if the EntryPopup behaviour is fine as is. Personally, I would rather the popup disappear when the main window is moved because it looks odd when it's left floating in the same position. I'm having trouble getting that functionality in place, however.
Review of attachment 147607 [details] [review]: Thanks Neil, looking really good. ::: src/Core/Banshee.ThickClient/Banshee.Collection.Gui/SearchableListView.cs @@ +50,3 @@ + private long search_offset = 0; + + public SearchableListView () : base () base () is superfluous @@ +55,3 @@ + + private QueryNode last_query = null; + public QueryNode LastQuery { can make this just "public QueryNode LastQuery { get; private set; } @@ +125,3 @@ + } + + if (last_query == null) { To better future-proof this, I think you should store/check last_query_fields too; a single ListView can be used by various models, and in the future the Podcast source might have a different set of fields but use the same ListView. @@ +128,3 @@ + last_query = BuildQueryTree (model.QueryFields, StringQueryValue.StartsWith, target); + } + else { put this on the same line as the } I also see quite a few of these below @@ +209,3 @@ + { + char input = Convert.ToChar (Gdk.Keyval.ToUnicode (press.KeyValue)); + if (!IsCharValid (input)) { Should probably check here also whether the model is ISearchable @@ +226,3 @@ + search_popup.HasFocus = true; + search_popup.Show (); + search_popup.Text = String.Format ("{0}{1}", search_popup.Text, Convert.ToChar (press.KeyValue)); Why do you convert to char here when you already have input? @@ +241,3 @@ + break; + case Gdk.Key.Down: + case Gdk.Key.KP_Down: Should handle F3 (ala Firefox) and Ctrl+G (ala GNOME HIG) for go-to-next-match, and shift+F3 and shift+ctrl+G for go-to-previous. @@ +244,3 @@ + previous_search_offset = search_offset++; + if (!PerformSearch (search_popup.Text)) { + search_offset = previous_search_offset; should we wrap around instead of staying at the previous match? ::: src/Core/Banshee.ThickClient/Banshee.Collection.Gui/SearchableTrackFilterListView.cs @@ +1,2 @@ +// +// SearchableTrackFilterListView.cs Why do you have this class and the modifications to TrackFilterListView? ::: src/Libraries/Hyena.Gui/Hyena.Widgets/EntryPopup.cs @@ +64,3 @@ + + text_entry.FocusOutEvent += (o, a) => { + Console.WriteLine ("focus out"); remove WriteLine @@ +90,3 @@ + } + +// public EntryPopup (Gtk.Widget widget) : this () Remove @@ +106,3 @@ +// } + + public EntryPopup (string text) : this () Move this to above the other ctor ::: src/Libraries/Hyena/Hyena.Data.Sqlite/SqliteModelCache.cs @@ +142,3 @@ + + //TODO this works, but is it reliable? Note JOIN on Value column + search_str = String.Format ( Using the select_str as the search_str doesn't work in this case? Ideally we could just reuse that. I think we should modify the select_str's to also grab CoreCache.OrderId directly - then we can avoid the IndexOf query and just return OrderId - FirstOrderId. This will help prevent bugs where a song is in a playlist twice and the type-ahead search has issues jumping to the 2nd entry.
Sorry about the style issues and debugging code I forgot to remove. (In reply to comment #31) > @@ +55,3 @@ > + > + private QueryNode last_query = null; > + public QueryNode LastQuery { > > can make this just "public QueryNode LastQuery { get; private set; } > Does that make last_query redundant? I guess I need to understand the reasoning. What if it were changed to: public QueryNode LastQuery { get { return last_query; } } ...and I just used last_query within the class? > > @@ +244,3 @@ > + previous_search_offset = search_offset++; > + if (!PerformSearch (search_popup.Text)) { > + search_offset = previous_search_offset; > > should we wrap around instead of staying at the previous match? > Not sure. When the list stops moving, you get visual feedback letting you know that there are no more search results in the direction you're scrolling. If it wrapped, it may not be as obvious. But, I could be wrong. The list normally doesn't wrap when either extreme is reached, so maybe for that reason it shouldn't wrap? Comments, anyone? > ::: > src/Core/Banshee.ThickClient/Banshee.Collection.Gui/SearchableTrackFilterListView.cs > @@ +1,2 @@ > +// > +// SearchableTrackFilterListView.cs > > Why do you have this class and the modifications to TrackFilterListView? > Sorry. I think this was just from me playing around with things, and I later forgot about it. Are you cool with TrackFilterListView subclassing SearchableListView? If so, SearchableTrackFilterListView can be removed. > > ::: src/Libraries/Hyena/Hyena.Data.Sqlite/SqliteModelCache.cs > @@ +142,3 @@ > + > + //TODO this works, but is it reliable? Note JOIN on Value > column > + search_str = String.Format ( > > Using the select_str as the search_str doesn't work in this case? > No, it doesn't work because when Model.CacheValues is true, select_str = "SELECT OrderID, ItemID FROM {0} WHERE {0}.ModelID = {1}". So, the QueryNode for the WHERE fragment is wrong. > Ideally we could just reuse that. I think we should modify the select_str's to > also grab CoreCache.OrderId directly - then we can avoid the IndexOf query and > just return OrderId - FirstOrderId. This will help prevent bugs where a song > is in a playlist twice and the type-ahead search has issues jumping to the 2nd > entry. Good idea. I'll work this in.
(In reply to comment #32) > Sorry about the style issues and debugging code I forgot to remove. No worries. > Does that make last_query redundant? I guess I need to understand the > reasoning. What if it were changed to: > public QueryNode LastQuery { > get { return last_query; } > } Yeah, it would make it redundant. Your approach is fine too - just a little more verbose. > Not sure. When the list stops moving, you get visual feedback letting you know > that there are no more search results in the direction you're scrolling. If it > wrapped, it may not be as obvious. But, I could be wrong. The list normally > doesn't wrap when either extreme is reached, so maybe for that reason it > shouldn't wrap? Comments, anyone? Well...since it'll be non-trivial to implement wrapping when going in reverse (since we'd have to know how many matches there are) - maybe we can just not wrap for now at least. > Sorry. I think this was just from me playing around with things, and I later > forgot about it. Are you cool with TrackFilterListView subclassing > SearchableListView? If so, SearchableTrackFilterListView can be removed. Yeah, that's fine. > No, it doesn't work because when Model.CacheValues is true, select_str = > "SELECT OrderID, ItemID FROM {0} WHERE {0}.ModelID = {1}". So, the QueryNode > for the WHERE fragment is wrong. It's only wrong b/c you're reusing the GenreField, etc, right? I think you could make a new QueryField just for use within the QueryFilterList, and set it's SQL column name to whatever will work - ItemID right?
Created attachment 147685 [details] [review] 5th iteration Applied your comments, Gabriel. SqlliteModelCache is using the select_str variable again with the OrderID added in. A new QueryField named QueryFilterField has been added to BansheeQuery. Another oddity I noticed with the EntryPopup is that the cursor is not visible even though the focus is on the Entry widget within it. I don't know why that is.
Review of attachment 147685 [details] [review]: Looking really good. Just a few more things. ::: src/Core/Banshee.Services/Banshee.Collection.Database/DatabaseQueryFilterModel.cs @@ +56,3 @@ ORDER BY Value"; + + QueryFields = new QueryFieldSet (Banshee.Query.BansheeQuery.QueryFilterField); Let's move QueryFilterField into this class, making it private. It's kind of a hack - very specific to the Cache stuff, and it's best if other people don't use it without really knowing what they're doing. ::: src/Core/Banshee.ThickClient/Banshee.Collection.Gui/SearchableListView.cs @@ +254,3 @@ + if ((press.State & Gdk.ModifierType.ShiftMask) != 0) { + search_backward = true; + break; unnecessary break; also, make the Key.G case like this one, with if/else @@ +267,3 @@ + if (search_forward) { + previous_search_offset = search_offset++; + if (!PerformSearch (search_popup.Text)) { there is an extra indentation space before this if ::: src/Libraries/Hyena/Hyena.Data.Sqlite/SqliteModelCache.cs @@ +243,3 @@ + + string sql = String.Format ("{0} {1} LIMIT {2}, 1", select_str, where_fragment, offset); +// Log.DebugFormat ("cache.IndexOf SQL = {0}", sql); Remove @@ +246,3 @@ + + lock (this) { + using (IDataReader reader = connection.Query (new HyenaSqliteCommand (sql))) { Could cache this HyenaSqliteCommand, and only regenerate it when where_fragment != last_indexof_where_fragment
(In reply to comment #35) > ::: src/Libraries/Hyena/Hyena.Data.Sqlite/SqliteModelCache.cs > > @@ +246,3 @@ > + > + lock (this) { > + using (IDataReader reader = connection.Query (new > HyenaSqliteCommand (sql))) { > > Could cache this HyenaSqliteCommand, and only regenerate it when where_fragment > != last_indexof_where_fragment While the where_fragment doesn't change when scrolling, the offset does. Therefore, the SQL command as a whole is almost always different for each IndexOf call because of the 'LIMIT offset, 1' parameter of the SQL command. Thus, a HyenaSqliteCommand object would have to be created almost every call, anyway. The only time the caching would kick in is when the user types a single char in the jump ahead, lets it disappear, and then they type the exact same char again. Still worthwhile?
IF instead of {2} you put ? for the offset, then you can reuse the same HyenaSqliteCommand, just passing in a new offset value each time: connection.Query (cmd, offset);
Created attachment 147697 [details] [review] 6th (In reply to comment #37) > IF instead of {2} you put ? for the offset, then you can reuse the same > HyenaSqliteCommand, just passing in a new offset value each time: > connection.Query (cmd, offset); Nice. Forgot about that. Here's another one for you.
Comment on attachment 147697 [details] [review] 6th I committed the patch to the new typeahead branch so we can iterate on it a bit more from there. Things left to do from my view: 1. figure out how to open it - maybe change / to open it and keep ctrl-f to focus the search box? I don't see us changing our single-key keybindings (space, p, f, n, etc) anytime soon. 2. Focus the entry so we get the focus highlighting and cursor Great job on this, Neil!
Awesome! and thanks. It was fun. :) In addition to your list of things to do, there's also this that I mentioned above: (In reply to comment #30) > I've noticed that the search popup for the SourceView, which is a subclass of > TreeView, behaves exactly (from my observations) like my new EntryPopup widget. > For example, when the main window is moved, the popup stays open. So, I'm > wondering if the EntryPopup behaviour is fine as is. Personally, I would rather > the popup disappear when the main window is moved because it looks odd when > it's left floating in the same position. I'm having trouble getting that > functionality in place, however. Looking forward to seeing this merged into master.
(In reply to comment #40) > (In reply to comment #30) > > the popup disappear when the main window is moved because it looks odd when > > it's left floating in the same position. I'm having trouble getting that I would think it would just move with the window. Let's add that to the todo list.
(In reply to comment #39) > > 1. figure out how to open it - maybe change / to open it and keep ctrl-f to > focus the search box? I don't see us changing our single-key keybindings > (space, p, f, n, etc) anytime soon. > Since the keybindings are now editable, many users change the single-key shortcuts to multi-key ones. For these users it makes sense to initiate the type-ahead action when any key is pressed. Do you think there's any chance this can be a configurable option? (even if only through gconf)
(In reply to comment #39) > 1. figure out how to open it - maybe change / to open it and keep ctrl-f to > focus the search box? I don't see us changing our single-key keybindings > (space, p, f, n, etc) anytime soon. Please keep in mind that for users of non-US/UK keyboards, "/" is not just a single key but may require two key presses (Shift+7 for de_CH). That makes it awkward and it loses the convenience of the usual GNOME type-ahead search. Also keep in mind that most users use multimedia keys if their keyboard has them, so they wouldn't need space, p, f, n. So +1 for a configuration option I guess.
Ok, I made it require '?' (shift-/ on US keyboards) for now, and merged into master. Please file new bugs with any changes you'd like made. I filed bug #603878 about the entry not being focused.
*** Bug 611739 has been marked as a duplicate of this bug. ***
Wow, I'm a bit discouraged to see that this seems to be something that everyone wants but hasn't been implemented in over 6 years. But anyway I'm throwing my hat in the ring of users in favor of this type of navigation, which is common in other players. As an iTunes veteran, the mapping of shortcuts directly to keyboard keys (as opposed to tied through chooser keys like shift or control) is a major bugbear. The requirement to enter the search bar to navigate quickly is cumbersome--in the situation where I'm jonesing for a particular track, but would like the shuffle of my full library to ensue, the need to remember to X out of the search selection seems unnecessary.
(In reply to Michael Chirico from comment #46) > Wow, I'm a bit discouraged to see that this seems to be something that > everyone wants but hasn't been implemented in over 6 years. This bug report is closed as FIXED. If your "this" is a different "this", feel free to file a new feature request. In general, volunteer manpower is always limited and the best approach to get a bug fixed is to contribute patches.