I'm building a small PyGTK application and I have an text input field (currently a ComboBoxEntry) which is populated with a few values that the user should be able to choose from.
I think what I want to do is to filter out the matching fields and only show those ones so the user using the keyboard arrows can choose one of the matching ones.
To give some background the predefined values are a bunch of urls and the user should be able to choose from theese or fill in a new one.
Example:
the predefined urls:
- http://www.google.com
- http://www.google.com/android
- http://www.greatstuff.com
- http://www.facebook.com
When a user types 'http://www.g'
The three URLs starting with that string is to be shown (in some way) and when typeing 'http://www.goog' the two starting with that is to be shown
Any Ideas?
An Entry
with an EntryCompletion
seems more appropriate than a ComboBoxEntry
. As always, the tutorial is a good start.
It's very easy to set up when the predefined URLs list is small and fixed.
You just need to populate a ListStore:
# simplified example from the tutorial
import gtk
urls = [
'http://www.google.com',
'http://www.google.com/android',
'http://www.greatstuff.com',
'http://www.facebook.com',
]
liststore = gtk.ListStore(str)
for s in urls:
liststore.append([s])
completion = gtk.EntryCompletion()
completion.set_model(liststore)
completion.set_text_column(0)
entry = gtk.Entry()
entry.set_completion(completion)
# boilerplate
window = gtk.Window()
window.add(entry)
window.connect('destroy', lambda w: gtk.main_quit())
window.show_all()
gtk.main()
Users are not likely to bother typing "http://" or even "www.", so you probably want to match any part of the URL (e.g. just "og" works!):
def match_anywhere(completion, entrystr, iter, data):
modelstr = completion.get_model()[iter][0]
return entrystr in modelstr
completion.set_match_func(match_anywhere, None)
This will test every value in the ListStore for a match, so it's not scalable to huge lists (I mean huge; a 1000 works fine).
Be sure to play with the various options of EntryCompletion, to configure the most pleasant behavior.
You may want to look at how Deskbar Applet's Cuemiac
does it.
Well, you obviously want to deal with prefixes so you'll probably want to use some sort of trie. Of course, there are issues to deal with. For instance, after a person has typed in a few letters ( or maybe even just one) you will want to either traverse the rest of the branches of the trie to find suggestions, or have suggestions stored in each node. A lot of these sorts of decisions depend on how many possible suggestions you plan on having.