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.

È stato utile?

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.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top