Deprecation warning: gtk.Tooltips deprecated in pygtk 2.12
[rox-lib.git] / ROX-Lib2 / python / rox / templates.py
blob52397e0b15e3d1b022bbcf6b39a30313aa1ac1b9
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 widgets=templates.load('main')
6 class MyWindow:
7 def __init__(self):
8 self.window=widgets.getWindow('main')
9 self.entry=widgets['text_entry']
10 widgets.autoConnect(self)
11 self.window.show_all()
14 To use a template as part of a class, derive a class from ProxyWindow
16 class MyWindow(templates.ProxyWindow):
17 def __init__(self, window, widgets):
18 templates.ProxyWindow.__init__(self, window, widgets)
20 self.cancel_button=widgets['cancel']
21 # ...
23 widgets=templates.load('main')
24 window=widgets.getWindow('main', MyWindow)
27 """
29 import os, sys
30 import errno
31 import UserDict
33 import rox
34 import gtk.glade as glade
36 def _get_templates_file_name(fname):
37 if not fname:
38 fname='Templates.glade'
39 if not os.path.isabs(fname):
40 fname=os.path.join(rox.app_dir, fname)
41 return fname
43 class ProxyWindow:
44 """This acts as a proxy for a GtkWindow or GtkDialog, except that
45 it calls the toplevel_(un)ref functions for you automatically.
46 It is designed to wrap a window loaded from a Glade template. You
47 can sub-class this to create your own classes."""
49 def __init__(self, window, widgets):
50 """Act as a proxy for window. Call toplevel_ref() and arrange
51 for toplevel_unref to be called on destruction. The signal
52 handlers are connected to this object."""
54 self._window=window
55 assert self._window
57 rox.toplevel_ref()
58 self._window.connect('destroy', rox.toplevel_unref)
60 widgets.signal_autoconnect(self)
62 def __getattr__(self, name):
63 """Get unrecognized attributes from the window we are proxying
64 for."""
65 try:
66 win=self.__dict__['_window']
67 except:
68 raise AttributeError, '_window'
70 if hasattr(win, name):
71 return getattr(win, name)
72 raise AttributeError, name
74 class Templates(glade.XML, UserDict.DictMixin):
75 """A set of widget instances created from a glade file."""
77 def __init__(self, root, fname=None, dict_or_instance=None):
78 """A set of widget instances created from the glade file.
79 root - top level widget to create (and all its contained widgets),
80 fname - file name to load the glade file from
81 dict_or_instance - either a dictionary where the
82 signal handlers are indexed by the name of the handler in the glade
83 file, or an instance of a class where the methods have the same
84 names as given in the glade file.
86 NOTE: if fname is None the glade file
87 is loaded from Templates.glade in the app dir.
88 """
90 if not fname:
91 fname=_get_templates_file_name(None)
93 glade.XML.__init__(self, fname, root)
95 if dict_or_instance:
96 self.signal_autoconnect(dict_or_instance)
98 def get_window(self, name, klass=ProxyWindow, *args, **kwargs):
99 """Return the named widget, which should be a gtk.Window. The
100 window is tracked by the window counting system, see
101 rox.toplevel_ref().
103 name - name of the widget
104 klass - Python class to wrap the widget in
105 args - arguments to pass to the constructor for klass after the
106 widget
107 kwargs - keyword arguments to pass to the constructor for klass"""
108 return klass(self.get_widget(name), self, *args, **kwargs)
110 # The next 4 methods let UserDict.DictMixin turn this class into
111 # something that behaves like a dict.
112 def __getitem__(self, key):
113 """Return the named widget."""
115 widget=self.get_widget(str(key))
116 if not widget:
117 raise KeyError, key
118 return widget
120 def __setitem__(self, key, value):
121 """Set a widget. Raises an exception."""
122 raise TypeError, 'read-only, cannot set '+key
124 def __delitem__(self, key):
125 """Delete a widget. Raises an exception."""
126 raise TypeError, 'read-only, cannot delete '+key
128 def keys(self):
129 """Return list of all named widgets."""
130 ws=self.get_widget_prefix("")
131 k=[]
132 for w in ws:
133 k.append(w.get_name())
134 return k
136 # More efficient implementations than UserDict.DictMixin
137 def values(self):
138 return self.get_widget_prefix("")
140 def itervalues(self):
141 ws=self.get_widget_prefix("")
142 for w in ws:
143 yield w
145 def load(root, fname=None, dict_or_instance=None):
146 """Load the templates file and return the set of widgets.
147 root - name of top level widget (and all child widgets) to create
148 fname - path to templates file: If it is an absolute path name then load
149 it, if a relative path name load that from the appdir or if None
150 the load $APP_DIR/Templates.glade.
151 dict_or_instance - what to use to connect the signals.
152 It is either a dictionary where the
153 signal handlers are indexed by the name of the handler in the glade
154 file, or an instance of a class where the methods have the same
155 names as given in the glade file.
157 return Templates(root, fname, dict_or_instance)