~happyaron/language-selector/lp-1468027

« back to all changes in this revision

Viewing changes to LanguageSelector/gtk/SimpleGladeApp.py

  • Committer: Bazaar Package Importer
  • Author(s): Michael Vogt, Loïc Minier, Sebastien Bacher
  • Date: 2009-07-29 10:10:55 UTC
  • Revision ID: james.westby@ubuntu.com-20090729101055-cv1fb19jfv7xeib4
Tags: 0.4.5
[ Loïc Minier ]
* Revert the change of 0.4.3 partially: keep parsing both double-quoted and
  non-quoted lines, but output double-quoted lines as in the past since this
  is consistent with localechooser, supported by pam_env and now also
  supported by sudo.

  [ Sebastien Bacher ]
* Use gtkbuilder rather than libglade (lp: #403531)

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("")