2015-03-14 2 views
0

Я пытаюсь добавить поле переключения в отфильтрованную модель для pygobjects. Я использовал код из учебника и добавил, чтобы добавить toggle renderer, но как только я щелкнул в отфильтрованном списке, переключатели отображаются неправильно.Pygobjects RenderToggle в отфильтрованной модели выбирает неправильный столбец

Предположим, у вас есть нефильтрованное список:

########################### 
# 0|test|a|toggle=False 
# 1|test|b|toggle=False 
# 2|test|a|toggle=False 
# 3|test|a|toggle=False 
########################## 

Когда теперь применить фильтр, говорят, что вы хотите видеть только пункты б вы получите:

# 1|test|b|toggle=False 

Если теперь нажать на что колонна, колонна из отфильтрованного списка «переключены», как путь 0, но должно быть 1:

# 0|test|a|toggle=True 

Но я хочу, конечно,:

# 1|test|b|toggle=True 

Так как мне это сделать?

Вот мой код, в основном скопированы с Учебник по http://python-gtk-3-tutorial.readthedocs.org/en/latest/treeview.html#filtering:

from gi.repository import Gtk 

#list of tuples for each software, containing the software name, initial release, and main programming languages used 
software_list = [("Firefox", 2002, "C++", False), 
       ("Eclipse", 2004, "Java", False), 
       ("Pitivi", 2004, "Python", False), 
       ("Netbeans", 1996, "Java", False), 
       ("Chrome", 2008, "C++", False), 
       ("Filezilla", 2001, "C++", False), 
       ("Bazaar", 2005, "Python", False), 
       ("Git", 2005, "C", False), 
       ("Linux Kernel", 1991, "C", False), 
       ("GCC", 1987, "C", False), 
       ("Frostwire", 2004, "Java", False)] 

class TreeViewFilterWindow(Gtk.Window): 

    def __init__(self): 
     Gtk.Window.__init__(self, title="Treeview Filter Demo") 
     self.set_border_width(10) 

     #Setting up the self.grid in which the elements are to be positionned 
     self.grid = Gtk.Grid() 
     self.grid.set_column_homogeneous(True) 
     self.grid.set_row_homogeneous(True) 
     self.add(self.grid) 

     #Creating the ListStore model 
     self.software_liststore = Gtk.ListStore(str, int, str, bool) 
     for software_ref in software_list: 
      self.software_liststore.append(list(software_ref)) 
     self.current_filter_language = None 

     #Creating the filter, feeding it with the liststore model 
     self.language_filter = self.software_liststore.filter_new() 
     #setting the filter function, note that we're not using the 
     self.language_filter.set_visible_func(self.language_filter_func) 

     #creating the treeview, making it use the filter as a model, and adding the columns 
     self.treeview = Gtk.TreeView.new_with_model(self.language_filter) 
     for i, column_title in enumerate(["Software", "Release Year", "Programming Language"]): 
      renderer = Gtk.CellRendererText() 
      column = Gtk.TreeViewColumn(column_title, renderer, text=i) 
      self.treeview.append_column(column) 
     renderer_toggle = Gtk.CellRendererToggle() 
     renderer_toggle.connect("toggled", self.on_cell_toggled) 
     column_toggle = Gtk.TreeViewColumn("toggle", renderer_toggle, active=3) 
     self.treeview.append_column(column_toggle) 

     #creating buttons to filter by programming language, and setting up their events 
     self.buttons = list() 
     for prog_language in ["Java", "C", "C++", "Python", "None"]: 
      button = Gtk.Button(prog_language) 
      self.buttons.append(button) 
      button.connect("clicked", self.on_selection_button_clicked) 

     #setting up the layout, putting the treeview in a scrollwindow, and the buttons in a row 
     self.scrollable_treelist = Gtk.ScrolledWindow() 
     self.scrollable_treelist.set_vexpand(True) 
     self.grid.attach(self.scrollable_treelist, 0, 0, 8, 10) 
     self.grid.attach_next_to(self.buttons[0], self.scrollable_treelist, Gtk.PositionType.BOTTOM, 1, 1) 
     for i, button in enumerate(self.buttons[1:]): 
      self.grid.attach_next_to(button, self.buttons[i], Gtk.PositionType.RIGHT, 1, 1) 
     self.scrollable_treelist.add(self.treeview) 

     self.show_all() 
    def on_cell_toggled(self, widget, path): 
     self.software_liststore[path][3] = not self.software_liststore[path][3] 

    def language_filter_func(self, model, iter, data): 
     """Tests if the language in the row is the one in the filter""" 
     if self.current_filter_language is None or self.current_filter_language == "None": 
      return True 
     else: 
      return model[iter][2] == self.current_filter_language 

    def on_selection_button_clicked(self, widget): 
     """Called on any of the button clicks""" 
     #we set the current language filter to the button's label 
     self.current_filter_language = widget.get_label() 
     print("%s language selected!" % self.current_filter_language) 
     #we update the filter, which updates in turn the view 
     self.language_filter.refilter() 


win = TreeViewFilterWindow() 
win.connect("delete-event", Gtk.main_quit) 
win.show_all() 
Gtk.main() 

ответ

2

path в on_cell_toggled() путь в фильтрованной модель так как это модель применяется к вашему GtkTreeView. Вам нужно будет преобразовать его в путь в нефильтрованной модели, прежде чем вы сможете это изменить. Для этого используйте метод отфильтрованной модели convert_path_to_child_path().

Если вы добавите сортировку позже, вам нужно будет сделать то же самое с вашей отсортированной моделью, и как с отсортированной моделью, так и с фильтрованной моделью вам нужно будет вызвать оба метода. Независимо от того, сколько слоев вы разместите поверх своей исходной модели, обработчик событий вашего рендеринга всегда даст вам путь к тому слою, о котором знает ваш GtkTreeView.

Те же правила применяются и к манипуляциям с выбором вида дерева.

+0

Я уже добавил сортировку, но я не хотел излишне затруднять мой вопрос. Ваше решение отлично работает. Теперь, когда у меня есть отсортированная и отфильтрованная модель, я сначала вызываю sorted_model.convert_path_to_child_path(), а затем filter_model.convert_path_to_child_path(), тогда как я создал отсортированную модель, например: self.sorted_and_filtered_model = Gtk.TreeModelSort (model = self.language_filter). Он работает нормально, но странно, что я должен использовать определенный порядок, чтобы получить правильный путь, есть ли лучший способ, или мне нужно сделать эти 2 зависимых звонка? – evildead

+0

Я не знаю лучшего способа, нет. GtkTreeView видит только вашу отсортированную или отфильтрованную модель (в зависимости от того, что вы ее дадите) и не знает о отсортированных или отфильтрованных моделях. Кроме того, вы также можете написать свою собственную модель, которая обтекает другой GtkTreeModel, и GtkTreeView не может знать об этом! Если * есть * объект для GtkTreeModelFilter и GtkTreeModelSort, я не знаю, что такое ti. (И я не знаю, добавили ли ваши привязки Python что-то подобное.) Удачи. :/Да, это должно быть в строгом порядке; подумайте об этих завернутых древовидных моделях как куклы Матрёшки. – andlabs

+0

спасибо за разъяснение этого для меня! – evildead

 Смежные вопросы

  • Нет связанных вопросов^_^