Re: Do TreeIters persist after foreach search ?
On Fri, 2007-11-09 at 11:29 +, Dave Howorth wrote: I've also noticed that there is some specific Gtk2-Perl documentation about iterators in the Gtk2::TreeModel description. I think the text is misleading as well as incomplete, especially since it differs from the underlying gtk+ functionality. So I'd suggest a change. Sounds good to me, committed. Thanks! -- Bye, -Torsten ___ gtk-perl-list mailing list gtk-perl-list@gnome.org http://mail.gnome.org/mailman/listinfo/gtk-perl-list
Re: Do TreeIters persist after foreach search ?
Torsten Schoenfeld wrote: On Thu, 2007-11-08 at 11:53 +, Dave Howorth wrote: I think there must be something I'm overlooking about iters. I have code which for testing I've simplified to the following: What works for me in Odot is storing a copy of the iterator: ... $match_iter = $iter-copy; Thanks, Torsten. I've just checked with my test program and it works for me too. I'm rewriting another way to get more efficiency, but I'll remember about Glib::Boxed-copy now you've introduced me to it! I've also noticed that there is some specific Gtk2-Perl documentation about iterators in the Gtk2::TreeModel description. I think the text is misleading as well as incomplete, especially since it differs from the underlying gtk+ functionality. So I'd suggest a change. Presently it says: ... These iterators are the primary way of accessing a model and are similar to the iterators used by Gtk2::TextBuffer. They are generally used only for a short time, and are valid only as long as the model is unchanged. The model interface defines a set of operations using them for navigating the model. How about something like: ... These iterators are the primary way of accessing a model and are similar to the iterators used by Gtk2::TextBuffer. The model interface defines a set of operations using them for navigating the model. The iterators are generally used only for a short time, and their behaviour is different to that suggested by the Gtk+ documentation. They are not valid when the model is changed, even though get_flags returns 'iters-persist'. Iterators obtained within a GtkTreeModelForeachFunc are also invalid after the foreach terminates. There may be other such cases. In the foreach case, and perhaps others, a persistent iterator may be obtained by copying it (see Glib::Boxed-copy) Sorry it's not very elegant but I don't know enough to be definitive! Cheers, Dave ___ gtk-perl-list mailing list gtk-perl-list@gnome.org http://mail.gnome.org/mailman/listinfo/gtk-perl-list
Do TreeIters persist after foreach search ?
I'm trying to write a method that locates a particular node in a Gtk2::TreeStore. I'm using the foreach method as the basis for walking the tree to find the node, but I'm having trouble extracting the resulting iter. I get errors like this: Gtk-CRITICAL **: gtk_tree_store_get_value: assertion `iter-stamp == GTK_TREE_STORE (tree_model)-stamp' failed I think there must be something I'm overlooking about iters. I have code which for testing I've simplified to the following: my $match_iter; $tree_store-foreach( sub { my ($tree_store, $path, $iter) = @_; my $level = $tree_store-get($iter, LEVEL); warn tree_store=$tree_store, iter=$iter;\n; $match_iter = $iter; return TRUE; }); warn search $tree_store = $match_iter;\n; my $level = $tree_store-get($match_iter, LEVEL); It prints tree_store=Gtk2::TreeStore=HASH(0x8283970), iter=Gtk2::TreeIter=SCALAR(0x43e28c48); search Gtk2::TreeStore=HASH(0x8283970) = Gtk2::TreeIter=SCALAR(0x43e28c48); Gtk-CRITICAL **: gtk_tree_store_get_value: assertion `iter-stamp == GTK_TREE_STORE (tree_model)-stamp' failed at [[[ the second get ]]] So the tree_store and the iter values seem to be the same but somehow the stamp is different and I can't see why. The gtk+ docs mention complications about the lifetime of iters but (a) I don't think what I'm doing causes the model to emit any signals and (b) the GtkTreeModelFlags include 'iters-persist' when I print them. The docs say Additionally, some models guarantee that an iterator is valid for as long as the node it refers to is valid (most notably the GtkTreeStore ... Any ideas what's happening, or better ways to find a node in the model? Cheers, Dave ___ gtk-perl-list mailing list gtk-perl-list@gnome.org http://mail.gnome.org/mailman/listinfo/gtk-perl-list
Re: Do TreeIters persist after foreach search ?
On Thu, 2007-11-08 at 11:53 +, Dave Howorth wrote: Any ideas what's happening, or better ways to find a node in the model? use a Gtk2::TreePath instead, which is meant to keep pointing to a row in the model (regardless of the fact if that row exists or if the data has been changed): # inside the foreach(): $match_path = $model-get_path($iter); and then: $iter = $model-get_iter($match_path); # always check retval $value = $model-get($iter, $column) if defined $iter; ciao, Emmanuele. -- Emmanuele Bassi, W: http://www.emmanuelebassi.net B: http://log.emmanuelebassi.net ___ gtk-perl-list mailing list gtk-perl-list@gnome.org http://mail.gnome.org/mailman/listinfo/gtk-perl-list
Re: Do TreeIters persist after foreach search ?
Emmanuele Bassi wrote: On Thu, 2007-11-08 at 11:53 +, Dave Howorth wrote: Any ideas what's happening, or better ways to find a node in the model? use a Gtk2::TreePath instead, which is meant to keep pointing to a row in the model (regardless of the fact if that row exists or if the data has been changed): # inside the foreach(): $match_path = $model-get_path($iter); the sub is already given the path as an arg so that can be simplified: $match_path = $path; and then: $iter = $model-get_iter($match_path); # always check retval I was trying to avoid this because I think it must do a second tree walk to reach the node? Which shouldn't be necessary. But I've switched to this technique at the moment unless anybody can suggest anything better. At the moment the search is way too slow. I'm just about to profile it to see whether I can fix it or whether I need to do my main tree handling outside of the gtk tree model and just use the gtk model as a display slave. I guess another alternative might be to reimplement foreach's tree walk myself which would lose the function call overhead and will probably avoid whatever weirdness is messing with the stamp. Thanks, Dave ___ gtk-perl-list mailing list gtk-perl-list@gnome.org http://mail.gnome.org/mailman/listinfo/gtk-perl-list
Re: Do TreeIters persist after foreach search ?
Dave Howorth wrote: I think there must be something I'm overlooking about iters. I have code which for testing I've simplified to the following: my $match_iter; $tree_store-foreach( sub { my ($tree_store, $path, $iter) = @_; my $level = $tree_store-get($iter, LEVEL); warn tree_store=$tree_store, iter=$iter;\n; $match_iter = $iter; return TRUE; }); warn search $tree_store = $match_iter;\n; my $level = $tree_store-get($match_iter, LEVEL); The iters are intended to be used on the stack in C, so for a foreach(), they would be destroyed before returning from the foreach() call. Instead, either store the $path or, better yet, the data from the row that you found, like this: my $row_data; $tree_store-foreach( sub { my ($tree_store, $path, $iter) = @_; my $this_row = [ $tree_store-get ($iter) ]; if (this_row_is_the_one_i_want ($this_row)) { $row_data = $this_row; return TRUE; } return FALSE; }); if (defined $row_data) { ... } Alternatively, you could just call the i-found-it-action in the foreach callback when you find the row you want, and avoid the issue. ___ gtk-perl-list mailing list gtk-perl-list@gnome.org http://mail.gnome.org/mailman/listinfo/gtk-perl-list
Re: Do TreeIters persist after foreach search ?
Dave Howorth wrote: Emmanuele Bassi wrote: $iter = $model-get_iter($match_path); # always check retval I was trying to avoid this because I think it must do a second tree walk to reach the node? Which shouldn't be necessary. It's not a full walk of the tree, so it's not heinously expensive, but you are correct that it is not free. But I've switched to this technique at the moment unless anybody can suggest anything better. See my other post in this thread. (I should've read the whole thread before replying...) At the moment the search is way too slow. I'm just about to profile it to see whether I can fix it or whether I need to do my main tree handling outside of the gtk tree model and just use the gtk model as a display slave. That path often leads to madness involving dual-data-structure synchronization and memory wastage. You may wish to investigate creating your own TreeModel implementation in that case, so that the TreeView will effectively display your native data structure. I guess another alternative might be to reimplement foreach's tree walk myself which would lose the function call overhead and will probably avoid whatever weirdness is messing with the stamp. I doubt that would save much, honestly. -- muppet scott at asofyet dot org ___ gtk-perl-list mailing list gtk-perl-list@gnome.org http://mail.gnome.org/mailman/listinfo/gtk-perl-list
Re: Do TreeIters persist after foreach search ?
muppet wrote: The iters are intended to be used on the stack in C, so for a foreach(), they would be destroyed before returning from the foreach() call. I saw the sentence about allocation on the stack but then it's followed by the specific 'guarantee that an iterator is valid for as long as the node it refers to is valid'. We learn by experience! Instead, either store the $path or, better yet, the data from the row that you found, like this: snip code Alternatively, you could just call the i-found-it-action in the foreach callback when you find the row you want, and avoid the issue. I'm trying this. I've basically inverted my algorithm so I can step through the gtk tree once and search a hash containing the matching data. (I should've read the whole thread before replying...) Thanks to you and Emmanuele for taking the time to help. Cheers, Dave ___ gtk-perl-list mailing list gtk-perl-list@gnome.org http://mail.gnome.org/mailman/listinfo/gtk-perl-list
Re: Do TreeIters persist after foreach search ?
On Thu, 2007-11-08 at 11:53 +, Dave Howorth wrote: I think there must be something I'm overlooking about iters. I have code which for testing I've simplified to the following: What works for me in Odot is storing a copy of the iterator: my $match_iter; $tree_store-foreach( sub { my ($tree_store, $path, $iter) = @_; my $level = $tree_store-get($iter, LEVEL); warn tree_store=$tree_store, iter=$iter;\n; $match_iter = $iter; $match_iter = $iter-copy; return TRUE; }); warn search $tree_store = $match_iter;\n; my $level = $tree_store-get($match_iter, LEVEL); -- Bye, -Torsten ___ gtk-perl-list mailing list gtk-perl-list@gnome.org http://mail.gnome.org/mailman/listinfo/gtk-perl-list