Уровень стека слишком глубокая ошибка Ruby-Gnome2 - PullRequest
0 голосов
/ 04 марта 2009

У меня есть Gtk :: TreeView с Gtk :: TreeModel и Gtk :: TreeModelFilter. Модель дерева выглядит так:

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

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

@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

вызывает вывод «ЭТА ОШИБКА: слишком большой уровень стека» для каждого итератора.

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

Ответы [ 2 ]

1 голос
/ 05 марта 2009

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 
1 голос
/ 04 марта 2009

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

переполнение стека

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

...