/[ascend]/trunk/pygtk/SimpleGladeApp.py
ViewVC logotype

Contents of /trunk/pygtk/SimpleGladeApp.py

Parent Directory Parent Directory | Revision Log Revision Log


Revision 532 - (show annotations) (download) (as text)
Mon Apr 24 02:23:08 2006 UTC (14 years, 1 month ago) by johnpye
File MIME type: text/x-python
File size: 11794 byte(s)
Removed 'interface' directory in trunk/pygtk/interface (moved everything up a level)
Made corresponding changes to SCons* and spec files.
1 """
2 SimpleGladeApp.py
3 Module that provides an object oriented abstraction to pygtk and libglade.
4 Copyright (C) 2004 Sandino Flores Moreno
5 """
6
7 # This library is free software; you can redistribute it and/or
8 # modify it under the terms of the GNU Lesser General Public
9 # License as published by the Free Software Foundation; either
10 # version 2.1 of the License, or (at your option) any later version.
11 #
12 # This library is distributed in the hope that it will be useful,
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 # Lesser General Public License for more details.
16 #
17 # You should have received a copy of the GNU Lesser General Public
18 # License along with this library; if not, write to the Free Software
19 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
20 # USA
21
22 import os
23 import sys
24 import re
25
26 import tokenize
27 import gtk
28 import gtk.glade
29 import weakref
30 import inspect
31
32 __version__ = "1.0"
33 __author__ = 'Sandino "tigrux" Flores-Moreno'
34
35 def bindtextdomain(app_name, locale_dir=None):
36 """
37 Bind the domain represented by app_name to the locale directory locale_dir.
38 It has the effect of loading translations, enabling applications for different
39 languages.
40
41 app_name:
42 a domain to look for translations, tipically the name of an application.
43
44 locale_dir:
45 a directory with locales like locale_dir/lang_isocode/LC_MESSAGES/app_name.mo
46 If omitted or None, then the current binding for app_name is used.
47 """
48 try:
49 import locale
50 import gettext
51 locale.setlocale(locale.LC_ALL, "")
52 gtk.glade.bindtextdomain(app_name, locale_dir)
53 gettext.install(app_name, locale_dir, unicode=1)
54 except (IOError,locale.Error), e:
55 print "Warning", app_name, e
56 __builtins__.__dict__["_"] = lambda x : x
57
58
59 class SimpleGladeApp:
60
61 def __init__(self, path, root=None, domain=None, **kwargs):
62 """
63 Load a glade file specified by glade_filename, using root as
64 root widget and domain as the domain for translations.
65
66 If it receives extra named arguments (argname=value), then they are used
67 as attributes of the instance.
68
69 path:
70 path to a glade filename.
71 If glade_filename cannot be found, then it will be searched in the
72 same directory of the program (sys.argv[0])
73
74 root:
75 the name of the widget that is the root of the user interface,
76 usually a window or dialog (a top level widget).
77 If None or ommited, the full user interface is loaded.
78
79 domain:
80 A domain to use for loading translations.
81 If None or ommited, no translation is loaded.
82
83 **kwargs:
84 a dictionary representing the named extra arguments.
85 It is useful to set attributes of new instances, for example:
86 glade_app = SimpleGladeApp("ui.glade", foo="some value", bar="another value")
87 sets two attributes (foo and bar) to glade_app.
88 """
89 if os.path.isfile(path):
90 self.glade_path = path
91 else:
92 glade_dir = os.path.dirname( sys.argv[0] )
93 self.glade_path = os.path.join(glade_dir, path)
94 for key, value in kwargs.items():
95 try:
96 setattr(self, key, weakref.proxy(value) )
97 except TypeError:
98 setattr(self, key, value)
99 self.glade = None
100 self.install_custom_handler(self.custom_handler)
101 self.glade = self.create_glade(self.glade_path, root, domain)
102 if root:
103 self.main_widget = self.get_widget(root)
104 else:
105 self.main_widget = None
106 self.normalize_names()
107 self.add_callbacks(self)
108 self.new()
109
110 def __repr__(self):
111 class_name = self.__class__.__name__
112 if self.main_widget:
113 root = gtk.Widget.get_name(self.main_widget)
114 repr = '%s(path="%s", root="%s")' % (class_name, self.glade_path, root)
115 else:
116 repr = '%s(path="%s")' % (class_name, self.glade_path)
117 return repr
118
119 def new(self):
120 """
121 Method called when the user interface is loaded and ready to be used.
122 At this moment, the widgets are loaded and can be refered as self.widget_name
123 """
124 pass
125
126 def add_callbacks(self, callbacks_proxy):
127 """
128 It uses the methods of callbacks_proxy as callbacks.
129 The callbacks are specified by using:
130 Properties window -> Signals tab
131 in glade-2 (or any other gui designer like gazpacho).
132
133 Methods of classes inheriting from SimpleGladeApp are used as
134 callbacks automatically.
135
136 callbacks_proxy:
137 an instance with methods as code of callbacks.
138 It means it has methods like on_button1_clicked, on_entry1_activate, etc.
139 """
140 self.glade.signal_autoconnect(callbacks_proxy)
141
142 def normalize_names(self):
143 """
144 It is internally used to normalize the name of the widgets.
145 It means a widget named foo:vbox-dialog in glade
146 is refered self.vbox_dialog in the code.
147
148 It also sets a data "prefixes" with the list of
149 prefixes a widget has for each widget.
150 """
151 for widget in self.get_widgets():
152 widget_name = gtk.Widget.get_name(widget)
153 prefixes_name_l = widget_name.split(":")
154 prefixes = prefixes_name_l[ : -1]
155 widget_api_name = prefixes_name_l[-1]
156 widget_api_name = "_".join( re.findall(tokenize.Name, widget_api_name) )
157 gtk.Widget.set_name(widget, widget_api_name)
158 if hasattr(self, widget_api_name):
159 raise AttributeError("instance %s already has an attribute %s" % (self,widget_api_name))
160 else:
161 setattr(self, widget_api_name, widget)
162 if prefixes:
163 gtk.Widget.set_data(widget, "prefixes", prefixes)
164
165 def add_prefix_actions(self, prefix_actions_proxy):
166 """
167 By using a gui designer (glade-2, gazpacho, etc)
168 widgets can have a prefix in theirs names
169 like foo:entry1 or foo:label3
170 It means entry1 and label3 has a prefix action named foo.
171
172 Then, prefix_actions_proxy must have a method named prefix_foo which
173 is called everytime a widget with prefix foo is found, using the found widget
174 as argument.
175
176 prefix_actions_proxy:
177 An instance with methods as prefix actions.
178 It means it has methods like prefix_foo, prefix_bar, etc.
179 """
180 prefix_s = "prefix_"
181 prefix_pos = len(prefix_s)
182
183 is_method = lambda t : callable( t[1] )
184 is_prefix_action = lambda t : t[0].startswith(prefix_s)
185 drop_prefix = lambda (k,w): (k[prefix_pos:],w)
186
187 members_t = inspect.getmembers(prefix_actions_proxy)
188 methods_t = filter(is_method, members_t)
189 prefix_actions_t = filter(is_prefix_action, methods_t)
190 prefix_actions_d = dict( map(drop_prefix, prefix_actions_t) )
191
192 for widget in self.get_widgets():
193 prefixes = gtk.Widget.get_data(widget, "prefixes")
194 if prefixes:
195 for prefix in prefixes:
196 if prefix in prefix_actions_d:
197 prefix_action = prefix_actions_d[prefix]
198 prefix_action(widget)
199
200 def custom_handler(self,
201 glade, function_name, widget_name,
202 str1, str2, int1, int2):
203 """
204 Generic handler for creating custom widgets, internally used to
205 enable custom widgets (custom widgets of glade).
206
207 The custom widgets have a creation function specified in design time.
208 Those creation functions are always called with str1,str2,int1,int2 as
209 arguments, that are values specified in design time.
210
211 Methods of classes inheriting from SimpleGladeApp are used as
212 creation functions automatically.
213
214 If a custom widget has create_foo as creation function, then the
215 method named create_foo is called with str1,str2,int1,int2 as arguments.
216 """
217 try:
218 handler = getattr(self, function_name)
219 return handler(str1, str2, int1, int2)
220 except AttributeError:
221 return None
222
223 def gtk_widget_show(self, widget, *args):
224 """
225 Predefined callback.
226 The widget is showed.
227 Equivalent to widget.show()
228 """
229 widget.show()
230
231 def gtk_widget_hide(self, widget, *args):
232 """
233 Predefined callback.
234 The widget is hidden.
235 Equivalent to widget.hide()
236 """
237 widget.hide()
238
239 def gtk_widget_grab_focus(self, widget, *args):
240 """
241 Predefined callback.
242 The widget grabs the focus.
243 Equivalent to widget.grab_focus()
244 """
245 widget.grab_focus()
246
247 def gtk_widget_destroy(self, widget, *args):
248 """
249 Predefined callback.
250 The widget is destroyed.
251 Equivalent to widget.destroy()
252 """
253 widget.destroy()
254
255 def gtk_window_activate_default(self, window, *args):
256 """
257 Predefined callback.
258 The default widget of the window is activated.
259 Equivalent to window.activate_default()
260 """
261 widget.activate_default()
262
263 def gtk_true(self, *args):
264 """
265 Predefined callback.
266 Equivalent to return True in a callback.
267 Useful for stopping propagation of signals.
268 """
269 return True
270
271 def gtk_false(self, *args):
272 """
273 Predefined callback.
274 Equivalent to return False in a callback.
275 """
276 return False
277
278 def gtk_main_quit(self, *args):
279 """
280 Predefined callback.
281 Equivalent to self.quit()
282 """
283 self.quit()
284
285 def main(self):
286 """
287 Starts the main loop of processing events.
288 The default implementation calls gtk.main()
289
290 Useful for applications that needs a non gtk main loop.
291 For example, applications based on gstreamer needs to override
292 this method with gst.main()
293
294 Do not directly call this method in your programs.
295 Use the method run() instead.
296 """
297 gtk.main()
298
299 def quit(self):
300 """
301 Quit processing events.
302 The default implementation calls gtk.main_quit()
303
304 Useful for applications that needs a non gtk main loop.
305 For example, applications based on gstreamer needs to override
306 this method with gst.main_quit()
307 """
308 gtk.main_quit()
309
310 def run(self):
311 """
312 Starts the main loop of processing events checking for Control-C.
313
314 The default implementation checks wheter a Control-C is pressed,
315 then calls on_keyboard_interrupt().
316
317 Use this method for starting programs.
318 """
319 try:
320 self.main()
321 except KeyboardInterrupt:
322 self.on_keyboard_interrupt()
323
324 def on_keyboard_interrupt(self):
325 """
326 This method is called by the default implementation of run()
327 after a program is finished by pressing Control-C.
328 """
329 pass
330
331 def install_custom_handler(self, custom_handler):
332 gtk.glade.set_custom_handler(custom_handler)
333
334 def create_glade(self, glade_path, root, domain):
335 return gtk.glade.XML(self.glade_path, root, domain)
336
337 def get_widget(self, widget_name):
338 return self.glade.get_widget(widget_name)
339
340 def get_widgets(self):
341 return self.glade.get_widget_prefix("")

john.pye@anu.edu.au
ViewVC Help
Powered by ViewVC 1.1.22