Reputation: 18246
I have a gtk widget and I want to find out if within its descendants there is another widget. If there is one, I want to return it otherwise return None. This is a simple recursive problem but I cannot seem to get the right method to do it.
In the glade xml file, I have:
<object class="GtkDialog" id="monkey">
[...]
<object class="GtkTreeView" id="ook">
and a call to find(my_monkey_object, 'ook')
should return the GtkTreeView object.
find()
should be something akin to
def find (node, id):
if node.XXX() == id: return node
for child in node.get_children():
ret = find(child, id)
if ret: return ret
return None
I am not sure which XXX() method I need to use. get_name()
looked hopeful but returns the class name of the object and not its "id". The version I use is pygtk-2.24.
See this Python GTK+ widget name question for the same problem.
Note that this bug kind of explains the issue: I want the builder ID as from a GTK widget tree. Sadly, this seems impossible to get...
Upvotes: 2
Views: 5274
Reputation: 1304
This answer has it.
Adapted to use pygi, it looks like:
# Copypasta from https://stackoverflow.com/a/20461465/2015768
# http://cdn.php-gtk.eu/cdn/farfuture/riUt0TzlozMVQuwGBNNJsaPujRQ4uIYXc8SWdgbgiYY/mtime:1368022411/sites/php-gtk.eu/files/gtk-php-get-child-widget-by-name.php__0.txt
# note get_name() vs gtk.Buildable.get_name(): https://stackoverflow.com/questions/3489520/python-gtk-widget-name
def get_descendant(widget, child_name, level, doPrint=False):
if widget is not None:
if doPrint: print("-"*level + ": " + (Gtk.Buildable.get_name(widget) or "(None)") + " :: " + (widget.get_name() or "(None)"))
else:
if doPrint: print("-"*level + ": " + "None")
return None
#/*** If it is what we are looking for ***/
if(Gtk.Buildable.get_name(widget) == child_name): # not widget.get_name() !
return widget;
#/*** If this widget has one child only search its child ***/
if (hasattr(widget, 'get_child') and callable(getattr(widget, 'get_child')) and child_name != ""):
child = widget.get_child()
if child is not None:
return get_descendant(child, child_name,level+1,doPrint)
# /*** Ity might have many children, so search them ***/
elif (hasattr(widget, 'get_children') and callable(getattr(widget, 'get_children')) and child_name !=""):
children = widget.get_children()
# /*** For each child ***/
found = None
for child in children:
if child is not None:
found = get_descendant(child, child_name,level+1,doPrint) # //search the child
if found: return found
Upvotes: 1
Reputation: 49019
According to the gtk C-api documentation, you can get the glade "id" name like this:
name = gtk_buildable_get_name (GTK_BUILDABLE (widget))
For pygtk, this is the same as
name = gtk.Buildable.get_name(widget)
Upvotes: 4
Reputation: 11614
I guess your node object is a gtk.Container derived class. Maybe isinstance(node, gtk.TreeView)
is what you are looking for. There is afaik no "id" per se in the gtk.Widget
-subclasses. The id field belongs to the glade-xml parser.
May i propose something like:
def find_child_classes(container, cls):
return [widget for widget in container.get_children() if isinstance(widget, cls)]
Or you keep the builder-object and access the instance by: builder.get_object('your-object-id')
.
Upvotes: 2