2
Copyright (C) 2004 Sandino Flores Moreno
4
This library is free software; you can redistribute it and/or
5
modify it under the terms of the GNU Lesser General Public
6
License as published by the Free Software Foundation; either
7
version 2.1 of the License, or (at your option) any later version.
9
This library is distributed in the hope that it will be useful,
10
but WITHOUT ANY WARRANTY; without even the implied warranty of
11
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12
Lesser General Public License for more details.
14
You should have received a copy of the GNU Lesser General Public
15
License along with this library; if not, write to the Free Software
16
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
19
simplegladeapp.py - Module that provides an object oriented abstraction
20
to pygtk and libglade.
22
- Adding `object' as base class to SimpleGladeApp class.
23
by Lincoln de Sousa <lincoln@archlinux-br.org>
25
- Commenting `setlocale' call to avoid problems with languages with
26
sufixes (as pt_BR.utf8) by Lincoln de Sousa <lincoln@archlinux-br.org>
29
from __future__ import absolute_import
30
from __future__ import division
31
from __future__ import print_function
47
__author__ = 'Sandino "tigrux" Flores-Moreno'
50
def bindtextdomain(app_name, locale_dir=None):
52
Bind the domain represented by app_name to the locale directory locale_dir.
53
It has the effect of loading translations, enabling applications for different
57
a domain to look for translations, tipically the name of an application.
60
a directory with locales like locale_dir/lang_isocode/LC_MESSAGES/app_name.mo
61
If omitted or None, then the current binding for app_name is used.
66
# FIXME: Commented to avoid problems with a .utf8 LANG variable...
67
# locale.setlocale(locale.LC_ALL, "")
68
gettext.bindtextdomain(app_name, locale_dir)
69
gettext.textdomain(app_name)
70
gtk.glade.bindtextdomain(app_name, locale_dir)
71
gtk.glade.textdomain(app_name)
72
gettext.install(app_name, locale_dir, unicode=1)
73
except (IOError, locale.Error), e:
74
print("Warning", app_name, e)
75
__builtins__.__dict__["_"] = lambda x: x
78
class SimpleGladeApp(object):
80
def __init__(self, path, root=None, domain=None, **kwargs):
82
Load a glade file specified by glade_filename, using root as
83
root widget and domain as the domain for translations.
85
If it receives extra named arguments (argname=value), then they are used
86
as attributes of the instance.
89
path to a glade filename.
90
If glade_filename cannot be found, then it will be searched in the
91
same directory of the program (sys.argv[0])
94
the name of the widget that is the root of the user interface,
95
usually a window or dialog (a top level widget).
96
If None or ommited, the full user interface is loaded.
99
A domain to use for loading translations.
100
If None or ommited, no translation is loaded.
103
a dictionary representing the named extra arguments.
104
It is useful to set attributes of new instances, for example:
105
glade_app = SimpleGladeApp("ui.glade", foo="some value", bar="another value")
106
sets two attributes (foo and bar) to glade_app.
108
if os.path.isfile(path):
109
self.glade_path = path
111
glade_dir = os.path.dirname(sys.argv[0])
112
self.glade_path = os.path.join(glade_dir, path)
113
for key, value in kwargs.items():
115
setattr(self, key, weakref.proxy(value))
117
setattr(self, key, value)
119
self.install_custom_handler(self.custom_handler)
120
self.glade = self.create_glade(self.glade_path, root, domain)
122
self.main_widget = self.get_widget(root)
124
self.main_widget = None
125
self.normalize_names()
126
self.add_callbacks(self)
130
class_name = self.__class__.__name__
132
root = gtk.Widget.get_name(self.main_widget)
133
repr = '%s(path="%s", root="%s")' % (class_name, self.glade_path, root)
135
repr = '%s(path="%s")' % (class_name, self.glade_path)
140
Method called when the user interface is loaded and ready to be used.
141
At this moment, the widgets are loaded and can be refered as self.widget_name
145
def add_callbacks(self, callbacks_proxy):
147
It uses the methods of callbacks_proxy as callbacks.
148
The callbacks are specified by using:
149
Properties window -> Signals tab
150
in glade-2 (or any other gui designer like gazpacho).
152
Methods of classes inheriting from SimpleGladeApp are used as
153
callbacks automatically.
156
an instance with methods as code of callbacks.
157
It means it has methods like on_button1_clicked, on_entry1_activate, etc.
159
self.glade.signal_autoconnect(callbacks_proxy)
161
def normalize_names(self):
163
It is internally used to normalize the name of the widgets.
164
It means a widget named foo:vbox-dialog in glade
165
is refered self.vbox_dialog in the code.
167
It also sets a data "prefixes" with the list of
168
prefixes a widget has for each widget.
170
for widget in self.get_widgets():
171
widget_name = gtk.Widget.get_name(widget)
172
prefixes_name_l = widget_name.split(":")
173
prefixes = prefixes_name_l[: -1]
174
widget_api_name = prefixes_name_l[-1]
175
widget_api_name = "_".join(re.findall(tokenize.Name, widget_api_name))
176
gtk.Widget.set_name(widget, widget_api_name)
177
if hasattr(self, widget_api_name):
178
raise AttributeError("instance %s already has an attribute %s" %
179
(self, widget_api_name))
181
setattr(self, widget_api_name, widget)
183
gtk.Widget.set_data(widget, "prefixes", prefixes)
185
def add_prefix_actions(self, prefix_actions_proxy):
187
By using a gui designer (glade-2, gazpacho, etc)
188
widgets can have a prefix in theirs names
189
like foo:entry1 or foo:label3
190
It means entry1 and label3 has a prefix action named foo.
192
Then, prefix_actions_proxy must have a method named prefix_foo which
193
is called everytime a widget with prefix foo is found, using the found widget
196
prefix_actions_proxy:
197
An instance with methods as prefix actions.
198
It means it has methods like prefix_foo, prefix_bar, etc.
201
prefix_pos = len(prefix_s)
203
is_method = lambda t: callable(t[1])
204
is_prefix_action = lambda t: t[0].startswith(prefix_s)
205
drop_prefix = lambda (k, w): (k[prefix_pos:], w)
207
members_t = inspect.getmembers(prefix_actions_proxy)
208
methods_t = filter(is_method, members_t)
209
prefix_actions_t = filter(is_prefix_action, methods_t)
210
prefix_actions_d = dict(map(drop_prefix, prefix_actions_t))
212
for widget in self.get_widgets():
213
prefixes = gtk.Widget.get_data(widget, "prefixes")
215
for prefix in prefixes:
216
if prefix in prefix_actions_d:
217
prefix_action = prefix_actions_d[prefix]
218
prefix_action(widget)
220
def custom_handler(self,
221
glade, function_name, widget_name,
222
str1, str2, int1, int2):
224
Generic handler for creating custom widgets, internally used to
225
enable custom widgets (custom widgets of glade).
227
The custom widgets have a creation function specified in design time.
228
Those creation functions are always called with str1,str2,int1,int2 as
229
arguments, that are values specified in design time.
231
Methods of classes inheriting from SimpleGladeApp are used as
232
creation functions automatically.
234
If a custom widget has create_foo as creation function, then the
235
method named create_foo is called with str1,str2,int1,int2 as arguments.
238
handler = getattr(self, function_name)
239
return handler(str1, str2, int1, int2)
240
except AttributeError:
243
def gtk_widget_show(self, widget, *args):
246
The widget is showed.
247
Equivalent to widget.show()
251
def gtk_widget_hide(self, widget, *args):
254
The widget is hidden.
255
Equivalent to widget.hide()
260
def gtk_widget_grab_focus(self, widget, *args):
263
The widget grabs the focus.
264
Equivalent to widget.grab_focus()
268
def gtk_widget_destroy(self, widget, *args):
271
The widget is destroyed.
272
Equivalent to widget.destroy()
276
def gtk_window_activate_default(self, widget, *args):
279
The default widget of the window is activated.
280
Equivalent to window.activate_default()
282
widget.activate_default()
284
def gtk_true(self, *args):
287
Equivalent to return True in a callback.
288
Useful for stopping propagation of signals.
292
def gtk_false(self, *args):
295
Equivalent to return False in a callback.
299
def gtk_main_quit(self, *args):
302
Equivalent to self.quit()
308
Starts the main loop of processing events.
309
The default implementation calls gtk.main()
311
Useful for applications that needs a non gtk main loop.
312
For example, applications based on gstreamer needs to override
313
this method with gst.main()
315
Do not directly call this method in your programs.
316
Use the method run() instead.
320
def quit(self, *args):
322
Quit processing events.
323
The default implementation calls gtk.main_quit()
325
Useful for applications that needs a non gtk main loop.
326
For example, applications based on gstreamer needs to override
327
this method with gst.main_quit()
333
Starts the main loop of processing events checking for Control-C.
335
The default implementation checks wheter a Control-C is pressed,
336
then calls on_keyboard_interrupt().
338
Use this method for starting programs.
342
except KeyboardInterrupt:
343
self.on_keyboard_interrupt()
345
def on_keyboard_interrupt(self):
347
This method is called by the default implementation of run()
348
after a program is finished by pressing Control-C.
352
def install_custom_handler(self, custom_handler):
353
gtk.glade.set_custom_handler(custom_handler)
355
def create_glade(self, glade_path, root, domain):
356
return gtk.glade.XML(glade_path, root, domain)
358
def get_widget(self, widget_name):
359
return self.glade.get_widget(widget_name)
361
def get_widgets(self):
362
return self.glade.get_widget_prefix("")