Error de nivel de pila demasiado profundo Ruby-Gnome2
-
03-07-2019 - |
Pregunta
Tengo un Gtk :: TreeView con un Gtk :: TreeModel y un Gtk :: TreeModelFilter. El modelo de árbol es así:
category1
--> actual row of data
category2
--> actual row of data
Quiero filtrar los contenidos de @search_entry, pero quiero que se muestre category1 si todavía está visible una fila debajo, y que se oculte category2 si no hay filas debajo de ella. Según entiendo Gtk :: TreeModelFilter # set_visible_func, obtienes el modelo y el iter del " child model " ;, para que puedas verificar si se muestra el iter secundario. Esta función se activa en cada iter en el modelo cada vez que llamo a Gtk :: TreeModelFilter # refilter. Por lo tanto, estoy diciendo: si el iter que acaba de darme está en el primer nivel, consiga el camino, baje el paso, conviértalo a la misma ruta en el modelo del filtro y use si la nueva ruta existe para probar la visibilidad.
@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
La línea
has_visible_children = @tree_filter.convert_child_path_to_path(iter_path) ? true : false
está causando un " ESTE ERROR: nivel de pila demasiado profundo " Salida para cada iter.
Aquí hay una recursión infinita, pero no veo dónde está sucediendo ni cómo puedo evitarlo. Estoy seguro de que estoy pensando en esto de manera equivocada, pero he estado hackeando esto un par de días sin un gran avance.
Solución
refilter
llama al bloque en cada nodo. Sin embargo, el valor de retorno no se guarda con el nodo, así que no importa cómo lo hagas, si tienes que mirar hacia abajo en el árbol, estarás repitiendo los cálculos.
# 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
Otros consejos
No sé nada acerca de Ruby, pero este error apunta claramente hacia demasiadas iteraciones de recursión. El contexto debe almacenarse en la pila para cada llamada, causando - hurray - a
desbordamiento de pila
:-) Agregue una variable para rastrear sus niveles de iteraciones e imprímala con el error. Hay algo mal con sus datos o la lógica de recursión, o ambos.