4

I am rewriting parts of the interface of an old Python program written using glade and PyGTK.

the program is rather complex, parts of the functionality is in plugins, so the original author has organized the interface definition in several glade files. also, some window define a generic interface, and then the specialization comes with its own widgets which fit in the generic GUI.

I have a perplexity on how to do this correctly using

from gi.repository import Gtk
builder = Gtk.Builder()

the builder, a global variable, holds all gtk objects defined in the glade files I pass it using its add_from_file method.

now I want to add several expanders, showing one line of info when collapsed and a picture and more textual info when expanded.

these expanders and the main window come all from the same picture_expander.glade file, which looks roughly like this:

<interface>
  <object class="GtkWindow" id="picture_preview_window">
    <child>
      <object class="GtkScrolledWindow" id="scrolledwindow2">
        <child>
          <object class="GtkViewport" id="viewport1">
            <child>
              <object class="GtkBox" id="notes_expander_box">
                <property name="orientation">vertical</property>
                <child>
                  <placeholder/>
                </child>
              </object>
            </child>
          </object>
        </child>
      </object>
    </child>
  </object>
  <object class="GtkBox" id="notes_box">
    <property name="orientation">vertical</property>
    <child>
      <object class="GtkExpander" id="notes_expander">
        <child>
          <object class="GtkBox" id="vbox2">
            <property name="orientation">vertical</property>
            <child>
              <object class="GtkTable" id="table1">
                <property name="n_columns">2</property>
                <child>
                  <object class="GtkLabel" id="label3">
                    <property name="label" translatable="yes">User</property>
                  </object>
                  <packing>
                    <property name="x_options">GTK_FILL</property>
                    <property name="y_options"/>
                  </packing>
                </child>
              </object>
              <packing>
              </packing>
            </child>
            <child>
              <object class="GtkBox" id="picture_frame">
                <property name="orientation">horizontal</property>
                <child>
                  <placeholder/>
                </child>
              </object>
            </child>
          </object>
        </child>
        <child type="label">
          <object class="GtkLabel" id="label1">
          </object>
        </child>
      </object>
    </child>
    <child>
      <object class="GtkSeparator" id="hseparator2">
        <property name="orientation">horizontal</property>
      </object>
    </child>
  </object>
</interface>

what is the correct way to do this?

if I add the picture_expander.glade to the builder, no matter how many times I add it, the builder will create one object and not many copies of it. if I understand correctly, this is exactly the reason why the builder class was introduced. but this way I do not get different objects I can add to my notes_expander_box container.

I see different options, but I don't know which is the safest and suggested.

I might clone the object and its content, but how do I do that? and what happens with the IDs, how do I refer to the newly cloned objects?

or, what I am doing now and works, for every expander I have to add to the notes_expander_box container, I create a new builder to which I pass the same file, and then ask the new builder to give me the object corresponding to the ID, so I end up with a new object and I can add it to my container.

# -*- coding: utf-8 -*-
#/usr/bin/env python

from gi.repository import Gtk
builder = Gtk.Builder()

builder.add_from_file("picture_preview.glade")

win = builder.get_object('picture_preview_window')

ne = builder.get_object('notes_expander_box')
for i in range(1, 4):
    tb = Gtk.Builder()
    tb.add_from_file("picture_preview.glade")
    box = tb.get_object('notes_box')
    ne.add(box)

win.show_all()
Gtk.main()

still, I don't think this is the way to go, as all the objects I am inserting all have the same ID.

or should I try to have something like Jinja2 generate the glade xml for me so that I can pass it to the global builder? with repetitions and unique IDs?

the last option I see is to leave glade alone and do at least this part programmaticly.

mariotomo
  • 9,438
  • 8
  • 47
  • 66
  • 1
    Your current method is the one that I use, though I don't know whether there's a better way. +1 and I hope to see an answer soon. – user12205 Apr 29 '15 at 07:54

1 Answers1

1

You can create another Gtk.Builder() and load only some objects(and childrens) in a file. Like:

tb=Gtk.Builder()
tb.add_objects_from_file(self.UI_XML, ("tab_header", "tab_body"))
tb.add_from_file(self.UI_XML)
tb.connect_signals(self)

tab_header=tb.get_object("tab_header")
tab_header.unparent()

tab_body=tb.get_object("tab_body")
tab_body.unparent()

self.filetab.insert_page(tab_body, tab_header, -1)