3 Module that provides an object oriented abstraction to pygtk and libglade.
4 Copyright (C) 2004 Sandino Flores Moreno
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.
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.
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
33 __author__ = 'Sandino "tigrux" Flores-Moreno'
35 def bindtextdomain(app_name, locale_dir=None):
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
42 a domain to look for translations, tipically the name of an application.
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.
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
61 def __init__(self, path, root=None, domain=None, **kwargs):
63 Load a glade file specified by glade_filename, using root as
64 root widget and domain as the domain for translations.
66 If it receives extra named arguments (argname=value), then they are used
67 as attributes of the instance.
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])
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.
80 A domain to use for loading translations.
81 If None or ommited, no translation is loaded.
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.
89 if os.path.isfile(path):
90 self.glade_path = path
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():
96 setattr(self, key, weakref.proxy(value) )
98 setattr(self, key, value)
100 self.install_custom_handler(self.custom_handler)
101 self.glade = self.create_glade(self.glade_path, root, domain)
103 self.main_widget = self.get_widget(root)
105 self.main_widget = None
106 self.normalize_names()
107 self.add_callbacks(self)
111 class_name = self.__class__.__name__
113 root = gtk.Widget.get_name(self.main_widget)
114 repr = '%s(path="%s", root="%s")' % (class_name, self.glade_path, root)
116 repr = '%s(path="%s")' % (class_name, self.glade_path)
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
126 def add_callbacks(self, callbacks_proxy):
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).
133 Methods of classes inheriting from SimpleGladeApp are used as
134 callbacks automatically.
137 an instance with methods as code of callbacks.
138 It means it has methods like on_button1_clicked, on_entry1_activate, etc.
140 self.glade.signal_autoconnect(callbacks_proxy)
142 def normalize_names(self):
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.
148 It also sets a data "prefixes" with the list of
149 prefixes a widget has for each widget.
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))
161 setattr(self, widget_api_name, widget)
163 gtk.Widget.set_data(widget, "prefixes", prefixes)
165 def add_prefix_actions(self, prefix_actions_proxy):
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.
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
176 prefix_actions_proxy:
177 An instance with methods as prefix actions.
178 It means it has methods like prefix_foo, prefix_bar, etc.
181 prefix_pos = len(prefix_s)
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)
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) )
192 for widget in self.get_widgets():
193 prefixes = gtk.Widget.get_data(widget, "prefixes")
195 for prefix in prefixes:
196 if prefix in prefix_actions_d:
197 prefix_action = prefix_actions_d[prefix]
198 prefix_action(widget)
200 def custom_handler(self,
201 glade, function_name, widget_name,
202 str1, str2, int1, int2):
204 Generic handler for creating custom widgets, internally used to
205 enable custom widgets (custom widgets of glade).
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.
211 Methods of classes inheriting from SimpleGladeApp are used as
212 creation functions automatically.
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.
218 handler = getattr(self, function_name)
219 return handler(str1, str2, int1, int2)
220 except AttributeError:
223 def gtk_widget_show(self, widget, *args):
226 The widget is showed.
227 Equivalent to widget.show()
231 def gtk_widget_hide(self, widget, *args):
234 The widget is hidden.
235 Equivalent to widget.hide()
239 def gtk_widget_grab_focus(self, widget, *args):
242 The widget grabs the focus.
243 Equivalent to widget.grab_focus()
247 def gtk_widget_destroy(self, widget, *args):
250 The widget is destroyed.
251 Equivalent to widget.destroy()
255 def gtk_window_activate_default(self, window, *args):
258 The default widget of the window is activated.
259 Equivalent to window.activate_default()
261 widget.activate_default()
263 def gtk_true(self, *args):
266 Equivalent to return True in a callback.
267 Useful for stopping propagation of signals.
271 def gtk_false(self, *args):
274 Equivalent to return False in a callback.
278 def gtk_main_quit(self, *args):
281 Equivalent to self.quit()
287 Starts the main loop of processing events.
288 The default implementation calls gtk.main()
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()
294 Do not directly call this method in your programs.
295 Use the method run() instead.
301 Quit processing events.
302 The default implementation calls gtk.main_quit()
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()
312 Starts the main loop of processing events checking for Control-C.
314 The default implementation checks wheter a Control-C is pressed,
315 then calls on_keyboard_interrupt().
317 Use this method for starting programs.
321 except KeyboardInterrupt:
322 self.on_keyboard_interrupt()
324 def on_keyboard_interrupt(self):
326 This method is called by the default implementation of run()
327 after a program is finished by pressing Control-C.
331 def install_custom_handler(self, custom_handler):
332 gtk.glade.set_custom_handler(custom_handler)
334 def create_glade(self, glade_path, root, domain):
335 return gtk.glade.XML(self.glade_path, root, domain)
337 def get_widget(self, widget_name):
338 return self.glade.get_widget(widget_name)
340 def get_widgets(self):
341 return self.glade.get_widget_prefix("")