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.

Foi útil?

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.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top