Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PyGtk How to change TreeView data using filter?

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?

like image 746
scarab Avatar asked Dec 28 '12 10:12

scarab


2 Answers

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

like image 141
César García Tapia Avatar answered Nov 05 '22 04:11

César García Tapia


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()
like image 2
scarab Avatar answered Nov 05 '22 04:11

scarab