Вопрос

What I'm trying to do is dynamically change (via filter) list of strings. In my case it is list of files with paths stored in gtk.TreeStore.

Example of expected effect (eg. Sublime Text 2 file searching Ctrl+P):

Data:

List of files (treeview):

  • '/home/user/'
    • '.bashrc',
    • 'test.txt',
  • ...

Action: In filter field (Entry widget) user starts typing. After first character eg. 't' list should be updated like this:

Result:

List of files (treeview):

  • 'test.txt',
  • ... all strings containing 't' (matching function is not important now)

What I already have:

self.search_entry = gtk.Entry()

self.tree_store = gtk.TreeStore(gobject.TYPE_STRING, gobject.TYPE_BOOLEAN)

for node, files in self.files_list:
    parent = self.tree_store.append(None, [node, True])
    for f in files:
        self.tree_store.append(parent, [f, True])

tree_filter = self.tree_store.filter_new()
self.treeview = gtk.TreeView(tree_filter)

self.renderer0 = gtk.CellRendererText()
self.treeview.insert_column_with_attributes(-1, "Filename", self.renderer0, text=0)
self.treeview.set_search_column(0)
self.treeview.set_search_entry(self.search_entry)
self.treeview.expand_all()

I know that TreeView has a method set_search_equal_func where I can change default matching function to my own. The problem is how can I change the list during typing in filter form field?

Это было полезно?

Решение

You must read about gtk.TreeModelFilter. Here you can read a very useful example. It's C#, but it's very easy to "translate" it to python:

http://www.mono-project.com/GtkSharp_TreeView_Tutorial#Filtering_Data

Другие советы

Thanks for that C# example link it was very useful. The key is to use gtk.TreeModelFilter methods set_visible_func and refilter.

Code looks like that now:

Somewhere in main app class:

def match_func(self, model, iterr, data=None):
    query = self.search_entry.get_buffer().get_text()
    value = model.get_value(iterr, 0)

    if query == "":
        return True
    elif query in value.lower():
        return True
    return False

def on_entry_refilter(self, widget, data=None):
    self.tree_filter.refilter()

Modified code:

self.search_entry = gtk.Entry()
self.search_entry.connect('changed', self.on_entry_refilter)

self.tree_store = gtk.TreeStore(gobject.TYPE_STRING, gobject.TYPE_BOOLEAN)

for node, files in self.files_list:
    parent = self.tree_store.append(None, [node, True])
    for f in files:
        self.tree_store.append(parent, [f, True])

self.tree_filter = self.tree_store.filter_new()
self.tree_filter.set_visible_func(self.match_func)
self.treeview = gtk.TreeView(self.tree_filter)

self.renderer0 = gtk.CellRendererText()
self.treeview.insert_column_with_attributes(-1, "Filename", self.renderer0, text=0)
self.treeview.set_search_column(0)
self.treeview.set_search_entry(self.search_entry)
self.treeview.expand_all()
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top