2009-03-04 2 views
0

У меня есть Gtk :: TreeView с Gtk :: TreeModel и Gtk :: TreeModelFilter. Дерево модели, как это:Уровень стека слишком глубокий Ошибка Ruby-Gnome2

category1 
    --> actual row of data 
category2 
    --> actual row of data 

Я хочу, чтобы фильтровать содержимое @search_entry, но я хочу category1 будет отображаться, если строка под ней все еще видно, и category2 быть скрыты, если есть нет строки под ним все еще видны. Мое понимание Gtk :: TreeModelFilter # set_visible_func заключается в том, что вы получаете модель и итера из «дочерней модели», чтобы вы могли проверить, показывать ли дочерний истер. Эта функция вызывается на каждом итерамере в модели каждый раз, когда я вызываю Gtk :: TreeModelFilter # refilter. Поэтому я говорю: если итер, который вы только что дали мне, находится на первом уровне, получите путь, перейдите на один, конвертируйте в один и тот же путь на модели фильтра и использовать ли новый путь для проверки видимости.

@store = Gtk::TreeStore.new(Gdk::Pixbuf, String, String, Menagerie::Program, TrueClass) 
@tree_filter = Gtk::TreeModelFilter.new(@store) 
@treeview.model = @tree_filter 

# @first_time gets set to false after the model is loaded the first time 
@first_time = true 
@tree_filter.set_visible_func do |model, iter| 
    has_visible_children = true 
    begin 
    iter_path = iter.path 
    if iter_path.depth == 1 && @first_time != true 
     iter_path.down! 
     has_visible_children = @tree_filter.convert_child_path_to_path(iter_path) ? true : false 
    end 
    rescue => e 
    puts "THIS ERROR: " + e.message 
    end 
    unless @search_entry.text == "" 
    if [1,2].collect {|i| iter[i] =~ /#{@search_entry.text}/i }.any? 
     true 
    elsif iter[4] == true and has_visible_children 
     true 
    else 
     false 
    end 
    else 
    true 
    end 
end 

Линия

has_visible_children = @tree_filter.convert_child_path_to_path(iter_path) ? true : false 

вызывает "Эта ошибка: уровень стека слишком глубоко" выход для каждого ITER.

Здесь бесконечная рекурсия, но я не вижу, где это происходит или как я могу ее избежать. Я уверен, что я думаю об этом неправильно, но я взламывал это через пару дней без прорыва.

ответ

1

refilter вызывает блок на каждом узле. Возвращаемое значение не сохраняется вместе с узлом, поэтому независимо от того, как вы это делаете, если вам нужно посмотреть вниз по дереву, вы будете повторять вычисления.

# Simplified version - returns true if search_text found in iter or any of its 
# first-level children. 
# Let's assume you add a method to GTK::TreeIter: 
# def has_text? search_text 
#  self[1] =~ /#{search_text}/i or self[2] =~ /#{search_text}/i 
# end 
@tree_filter.set_visible_func do |model, iter| 
    next true if @search_entry.text.empty? # No filtering if no search text 
    next true if iter.path.depth == 0  # Always show root node 
    next true if iter.has_text? @search_entry.text 

    if child_iter = iter.first_child # Then we have children to check 
    has_visible_children = false 
    loop do 
     has_visible_children ||= child_iter.has_text? @search_entry.text 
     break unless child_iter.next! # returns false if no more children 
    end 
    next has_visible_children 
    end 

    next false # Not root, doesn't contain search_text, has no children 
end 
+0

Хорошо, я вижу. Мы можем все понять из TreeModel, не беспокоясь о TreeModelFilter. И вы очистили мой код! Спасибо, Сара. – method

1

Я ничего не знаю о Ruby, но эта ошибка явно указывает на слишком много итераций рекурсии. Контекст должен быть сохранен в стеке для каждого вызова, в результате чего - ура - это

stack overflow

:-) Добавить переменную для отслеживания уровней итераций и распечатать его с ошибкой. С вашими данными или логикой рекурсии есть что-то не то, или то и другое.