GNOME Bugzilla – Bug 81534
Re-implement STL-style interface for Gtk::Notebook.
Last modified: 2004-12-22 21:47:04 UTC
Gtk::Notebook is missing an STL-stlye interface at the moment. This is very bad since it is a common task to iterate the Pages of your Notebook if you have an app that has multiple views. This interface cannot work directly on the GList that is owned by GtkNotebook because the data structure is not revealed by gtk (which was the reason why the former STL-style interface has been removed). Instead the iterator has to hold a pointer to the Notebook so that the output class (that may inherit the iterator privately as in TreeRow/TreeIter) can retrieve and manipulate its (virtual) data with the API-functions provided by Notebook. My patch that will be attached in a few seconds implements the STL-style interface as described above. The interface has been discussed with Daniel on IRC. examples/notebook demonstrates it's usage.
Created attachment 8399 [details] [review] The promised patch...
This needs some extra comments to explain its use of the GList*. It seems to use g_list_* functions just to step through the children and to test for iterator equality, but why don't you just use the child index number for that?
Because I persuaded him to do so. The point is, even if you use a child index number, you would still have to use g_list_length() to retrieve the number of elements. And using an element index results in iterators not staying valid on insertion/removal. This would only lead to fragile and unexpected behaviour.
Thanks for your splendid explanation Daniel! I will add revise my patch to include this comment. Meanwhile, as discussed with Murray on IRC, I'm asking on the gtk-devel-list whether it is safe to use the "children" member to struct _GtkNotebook language bindings.
Would it be totally unacceptable for the iterator to be invalidated after removal/insertion?
Am 17.05.2002 20:03 schrieb(en) Owen Taylor: > MHL.Schulze@t-online.de (Martin Schulze) writes: > > Hello! > > > > Maybe my former mail was not clear enough. So now in simpler words: > > > > - How can I determine the number of pages in a GtkNotebook-Widget? > > - Is is safe to use g_list_length(my_notebook.children)? > > No, but you might be able to get away with it. The only documented > exported way of getting the number of pages is to use > gtk_container_children(), > and you really should do that. > > > - Furthermore: Will the pointers stored in my_notebook.children stay > > valid when inserting/deleting a page to my_notebook so that it's safe > > to use g_list_position(my_notebook.children, node) to determine the > > position of a page? > > No. It's completely undefined what's in that list. > gtk_notebook_page_num() > gives you the mapping from page widget to page number. Okay, my interpretation: The GList returned by gtk_container_get_children() can in theory be used to navigate through the pages-list. It is however not guaranteed that the page with g_list_position()==1 is the second page shown. Also it is not guaranteed that the page that has something to do with node xy in the GList will still be in the GList after inserting/deleting a page. These two points are theoretical in my opinion. I would vote for still using the GList for navigation through the pages-list (of course using gtk_container_get_children() to obtain the pointer).
Sorry, I must repeat myself. I made two serious typing errors. The GList returned by gtk_container_get_children() _can_ be used to navigate through the pages-list. It is however not guaranteed that the page with g_list_position()==1 is the second page shown. Also it is not guaranteed that the node in the GList that has something to do with page num xy will still be in the GList after inserting / deleting a page. These two points are theoretical in my opinion. I would vote for still using the GList for navigation through the pages-list (of course using gtk_container_get_children() to obtain the pointer). I revised my patch to use gtk_container_get_children and added an explanation why we should use the GList at all.
Created attachment 8573 [details] [review] The revised patch...
Unfortunately it won't work that way, because gtk_container_get_children() returns a newly allocated GList. So this means a) the current patch is broken, since glist() tries returning a reference to a temporary, and the GList is never freed too. And much worse, b) by operating on a copy of the internal GList, we lose the persistent iterators. Sigh. This is getting nasty now. If accessing the private GList isn't an option, we probably have to use element indices. That also means PageList should be renamed to PageVector. And we'll have the most expensive size() method I ever heard of.
ARGH! Fortunately there are more than my two wary eyes that have a look on patches before applying :) But this is _really_ nasty now: Our other STL-style wrappers (namely ToolList - I haven't looked at the rest) use the private "children" member in the structs they are working on, too. Now, there we don't even have the option using indices because there are no appropriate API-functions in gtk+ for GtkToolbar, etc. Now Daniel, Murray, I believe it's a maintainer's choice: Don't provide any STL-style wrappers or illegally use the private "children" member of the gtk+-structs in all these classes (including PageList).
I don't think that the others are quite so private. This one is really private because the declaration of the element type is hidden. If we use internals then GTK+3 will just hide them more forcibly. Also, we can not expect any help from the GTK* people if something doesn't work.
If the children member of GtkNotebook will be completely hidden in future versions of gtk it is very likely that it will be hidden in other container widget, too and vice versa. (GtkNotebook _is_ a container widget - this won't change and it's as likely as for any other container widget that future version of gtk will deal it in a special way.) This is the basis of my argumentation and the reason why I created that patch at all. It's the most logical and objective reasoning I can think of in this matter. If you don't follow it I'll give up the thing and use it in my private code. Remember that with my patch we don't make any assumptions about the hidden data struct. We do however assume that every child in the container has something to do with a notebook page and that the order of the child elements in the list is the same as the "num"-index of the corresponding notebook page.
Yes, my argument is tenuous. I'm just trying to avoid removing _all_ STL-style interfaces. I guess if it works then it has as much right to exist as the others. I remove my objections. What do you think, Daniel?
Well. I know it's against the rules, but I think that's OK in this particular case (Havoc or Owen once mentioned language bindings might sometimes need to access private data -- unfortunately I haven't found the relevant mail again.) This part of the GtkNotebook implementation is quite unlikely to change in binary-compatible releases -- at least I suppose so. If all of the code that accesses private data is out-of-line, we'll still have a chance to hack around it if the worst-case scenario happens. At least we got rid of the ripped struct _GtkNotebookChild definition, which was seriously braindead.
Created attachment 8703 [details] [review] Difference from last patch: use gparent_->children instead of gtk_container_get_children again.
So could someone apply this then?
I applied this now with some tweaks (basically, cleaning up the most disgusting bits and moving stuff out of line). It still looks horrible though -- the code definitely needs some loving. Don't get me wrong, Martin -- the stuff you implemented was perfect. I'm targetting the original developer... ;-)