nível de pilha de erro muito profundo Rubi-Gnome2
-
03-07-2019 - |
Pergunta
Eu tenho um Gtk :: TreeView com um Gtk :: TreeModel e um Gtk :: TreeModelFilter. A Árvore Modelo é assim:
category1
--> actual row of data
category2
--> actual row of data
Eu quero filtro sobre o conteúdo de @search_entry, mas eu quero categoria1 a ser exibido se uma linha sob ela ainda é visível, e categoria2 para ser escondida, se não houver linhas abaixo é ainda visível. O meu entendimento de Gtk :: TreeModelFilter # set_visible_func é que você começa o modelo e iter do "modelo de criança", de modo que você pode verificar se a exibir o iter criança. Esta função é chamada em cada iter no modelo cada vez que eu chamar Gtk :: TreeModelFilter # refilter.Therefore que estou dizendo: se o iter você só me deu é no primeiro nível, obter o caminho, passo para baixo um, convertido ao o mesmo caminho do modelo e da utilização do filtro se o novo caminho existe a visibilidade teste.
@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
A linha
has_visible_children = @tree_filter.convert_child_path_to_path(iter_path) ? true : false
está causando um "Este erro: nível de pilha muito profundo" de saída para cada iter.
Há uma recursão infinita acontecendo aqui, mas eu não vejo onde isso está acontecendo ou como posso evitá-lo. Eu estou certo que eu estou pensando sobre isso da maneira errada, mas eu tenho sido hacking sobre este um par de dias sem um avanço.
Solução
refilter
chama o bloco em cada nó. O valor de retorno não é salvo com o nó, embora, por isso não importa como você fazer isso, se você tem que olhar para baixo da árvore, você estará repetindo 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
Outras dicas
Não sei nada sobre Ruby, mas este erro aponta claramente para muitas iterações de recursão. As necessidades de contexto para ser armazenado na pilha para cada chamada, causando - hurray - um
estouro de pilha
:-) Adicionar uma variável para controlar seus níveis de iterações e imprimi-lo com o erro. Há tanto de errado algo com seus dados ou a lógica recursão, ou ambos.