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.

Était-ce utile?

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.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top