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.

¿Fue útil?

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.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top