Erreur de niveau de pile trop profonde Ruby-Gnome2
-
03-07-2019 - |
Question
J'ai un Gtk :: TreeView avec un Gtk :: TreeModel et un Gtk :: TreeModelFilter. Le modèle d'arbre ressemble à ceci:
category1
--> actual row of data
category2
--> actual row of data
Je souhaite filtrer le contenu de @search_entry, mais je souhaite que category1 soit affiché si une ligne en dessous est toujours visible et que category2 est masqué s'il n'y a aucune ligne sous celle-ci. D'après ce que je comprends de Gtk :: TreeModelFilter # set_visible_func, vous obtenez le modèle et son itérateur à partir du "modèle enfant", de sorte que vous puissiez vérifier si elle doit être affichée. Cette fonction est appelée à chaque itération du modèle à chaque fois que j'appelle Gtk :: TreeModelFilter # refilter.Par conséquent, je dis: si l'itérateur que vous venez de me donner est au premier niveau, obtenez le chemin, descendez-en un, convertissez-le en Utilisez le même chemin sur le modèle du filtre et indiquez si le nouveau chemin existe pour tester la visibilité.
@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 ligne
has_visible_children = @tree_filter.convert_child_path_to_path(iter_path) ? true : false
provoque une erreur "CETTE ERREUR: le niveau de pile est trop profond". sortie pour chaque iter.
Il y a une récursion infinie ici, mais je ne vois pas où cela se passe ni comment je peux l'éviter. Je suis sûr que je pense à cela dans le mauvais sens, mais cela fait quelques jours que je pirate sans rien faire.
La solution
refilter
appelle le bloc sur chaque noeud. La valeur de retour n'est pas enregistrée avec le nœud, cependant, quelle que soit la façon dont vous le faites, si vous devez regarder dans l'arborescence, vous répéterez les calculs.
# 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
Autres conseils
Je ne connais rien à Ruby, mais cette erreur indique clairement trop d'itérations de récursivité. Le contexte doit être stocké sur la pile pour chaque appel, ce qui provoque - hourra - a
débordement de pile
:-) Ajoutez une variable pour suivre vos niveaux d'itérations et imprimez-la avec l'erreur. Il y a soit un problème avec vos données, soit la logique de récursivité, soit les deux.