Fix syntax error in getting the widget set (Stephen Watson).
[rox-lib.git] / ROX-Lib2 / python / rox / templates.py
blobdd9a478d844351c24ee768575f33591f365d91b4
1 """Support for loading glade files from your application directory.
3 The simplest interface will be templates.load() which will return a set
4 of widgets loaded from $APP_DIR/Templates.glade, e.g.
5 class MyWindow:
6 def __init__(self):
7 widgets=templates.load()
8 self.window=widgets.getWindow('main')
9 self.entry=widgets['text_entry']
10 widgets.autoConnect(self)
11 self.window.show_all()
13 If you wish to re-use a window then you should use the Templates class:
14 widgets=templates.Templates()
15 windows=[]
16 for i in range(10):
17 set=widgets.getWidgetSet('main')
18 # ... connect signal handlers
19 window=set.getWindow('main')
20 windows.append(window)
21 """
23 import os, sys
24 import errno
26 import rox
27 import gtk.glade as glade
29 def _get_templates_file_name(fname):
30 if not fname:
31 fname='Templates.glade'
32 if not os.path.isabs(fname):
33 fname=os.path.join(rox.app_dir, fname)
34 return fname
36 def _wrap_window(win):
37 if not win.get_data('rox_toplevel_ref'):
38 rox.toplevel_ref()
39 win.connect('destroy', rox.toplevel_unref)
40 win.set_data('rox_toplevel_ref', True)
41 return win
43 class Templates:
44 """Class holding a loaded glade file."""
46 def __init__(self, name=None):
47 """Load the glade file. If name is an absolute path name then load
48 it, if a relative path name load that from the appdir or if None
49 the load $APP_DIR/Templates.glade."""
50 self.fname=_get_templates_file_name(name)
52 # Ideally we should cache the file then generate the widgets
53 # using glade.xml_new_from_buffer(), but that is too buggy
54 #self.xml=file(self.fname, 'r').read()
55 self.connect_to=None
56 self.signals={}
58 def autoConnect(self, dict_or_instance):
59 """Specify what to use to connect the signals when an instance of the
60 widgets is created. dict_or_instance is either a dictionary where the
61 signal handlers are indexed by the name of the handler in the glade
62 file, or an instance of a class where the methods have the same
63 names as given in the glade file."""
65 self.connect_to=dict_or_instance
67 def connect(self, handler_name, func):
68 """Manually specify the handler function for a signal. These are
69 not set until getWidgetSet is called."""
71 self.signals[handler_name]=func
73 def getWidgetSet(self, root=''):
74 """Return a WidgetSet instance containing the widgets defined by
75 the glade file. If root is given it is the top level widget to return.
76 The signal handlers specified in connect() or autoConnect() are
77 connected at this point.
78 """
80 widgets=WidgetSet(fname=self.fname, root=root)
81 if self.connect_to:
82 widgets.autoConnect(self.connect_to)
83 for name in self.signals:
84 widgets.connect(name, self.signals[name])
85 return widgets
87 class WidgetSet:
88 """A set of widget instances created from a glade file."""
90 def __init__(self, xml=None, fname=None, root=''):
91 """A set of widget instances created from the glade file.
92 xml - the contents of the glade file.
93 fname - file name to load the glade file from
94 root - top level widget to create (and all is contained widgets), or
95 '' to create all.
96 NOTE: one of xml or fname must be specified
97 """
99 assert xml or fname
101 if fname:
102 self.widgets=glade.XML(fname, root)
103 else:
104 self.widgets=glade.xml_new_from_buffer(xml, len(xml), root)
106 def autoConnect(self, dict_or_instance):
107 """Specify what to use to connect the signals.
108 dict_or_instance is either a dictionary where the
109 signal handlers are indexed by the name of the handler in the glade
110 file, or an instance of a class where the methods have the same
111 names as given in the glade file."""
113 self.widgets.signal_autoconnect(dict_or_instance)
115 def connect(self, name, func):
116 """Manually specify the handler function for a signal."""
118 self.widgets.signal_connect(name, func)
120 def getWidget(self, name):
121 """Return the named widget."""
122 return self.widgets.get_widget(name)
124 def getWindow(self, name):
125 """Return the named widget, which should be a gtk.Window. The
126 window is tracked by the window counting system, see
127 rox.toplevel_ref()."""
128 return _wrap_window(self.getWidget(name))
130 def __getitem__(self, key):
131 """Return the named widget."""
133 widget=self.widgets.get_widget(key)
134 if not widget:
135 raise KeyError, key
136 return widget
138 def load(fname=None, root='', dict_or_instance=None):
139 """Load the templates file and return the set of widgets.
140 fname - path to templates file: If it is an absolute path name then load
141 it, if a relative path name load that from the appdir or if None
142 the load $APP_DIR/Templates.glade.
143 root - name of top level widget (and all child widgets) to create
144 dict_or_instance - what to use to connect the signals.
145 It is either a dictionary where the
146 signal handlers are indexed by the name of the handler in the glade
147 file, or an instance of a class where the methods have the same
148 names as given in the glade file.
150 template=Templates(fname)
151 if dict_or_instance:
152 template.autoConnect(dict_or_instance)
153 return template.getWidgetSet(root)