Livello di stack troppo profondo errore Ruby-Gnome2
-
03-07-2019 - |
Domanda
Ho un Gtk :: TreeView con un Gtk :: TreeModel e un Gtk :: TreeModelFilter. Il modello ad albero è così:
category1
--> actual row of data
category2
--> actual row of data
Voglio filtrare il contenuto di @search_entry, ma voglio che venga visualizzata la categoria1 se una riga sotto di essa è ancora visibile e la categoria 2 da nascondere se non ci sono righe sotto di essa ancora visibili. La mia comprensione di Gtk :: TreeModelFilter # set_visible_func è che ottieni il modello e l'iter dal "modello figlio", in modo da poter verificare se visualizzare l'iter secondario. Questa funzione viene chiamata su ogni iter nel modello ogni volta che chiamo Gtk :: TreeModelFilter # refilter. Pertanto sto dicendo: se l'iter che mi hai appena dato è al primo livello, ottieni il percorso, scendi uno, convertilo in lo stesso percorso sul modello del filtro e usa se esiste il nuovo percorso per testare 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 linea
has_visible_children = @tree_filter.convert_child_path_to_path(iter_path) ? true : false
sta causando un " QUESTO ERRORE: livello di stack troppo profondo " output per ogni iter.
C'è una ricorsione infinita in corso qui, ma non vedo dove stia succedendo o come posso evitarlo. Sono sicuro che ci sto pensando nel modo sbagliato, ma ci ho hackerato un paio di giorni senza una svolta.
Soluzione
refilter
chiama il blocco su ogni nodo. Tuttavia, il valore restituito non viene salvato con il nodo, quindi, indipendentemente da come lo fai, se devi guardare l'albero, dovrai ripetere i calcoli.
# 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
Altri suggerimenti
Non so nulla di Ruby, ma questo errore indica chiaramente troppe iterazioni di ricorsione. Il contesto deve essere archiviato nello stack per ogni chiamata, causando - hurray - a
overflow dello stack
:-) Aggiungi una variabile per tenere traccia dei tuoi livelli di iterazioni e stampala con l'errore. C'è qualcosa di sbagliato nei tuoi dati o nella logica di ricorsione, o entrambi.