~ubuntu-branches/ubuntu/oneiric/language-selector/oneiric

« back to all changes in this revision

Viewing changes to LanguageSelector/gtk/SimpleGladeApp.py

  • Committer: Bazaar Package Importer
  • Author(s): Michael Vogt
  • Date: 2006-03-21 14:48:05 UTC
  • Revision ID: james.westby@ubuntu.com-20060321144805-at0hubvraxfxzvwb
Tags: 0.1.13
* add a qt fontend 
* build langauge-selector-common, language-selector-qt now
* only show a single row for both langauge-pack and language-support
* fix typo in ko_KR fontconfig voodoo file (ubuntu: #35817)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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("")