pygtk get widget by name from parent node

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

Answers (3)

Frederick Nord
Frederick Nord

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

ergosys
ergosys

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

Don Question
Don Question

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

Related Questions