~ubuntu-branches/debian/sid/guake/sid

« back to all changes in this revision

Viewing changes to src/guake/simplegladeapp.py

  • Committer: Package Import Robot
  • Author(s): Daniel Echeverry
  • Date: 2015-04-26 19:15:06 UTC
  • mfrom: (1.1.7)
  • mto: This revision was merged to the branch mainline in revision 26.
  • Revision ID: package-import@ubuntu.com-20150426191506-mo8037vk6pueer5b
Tags: upstream-0.7.0
ImportĀ upstreamĀ versionĀ 0.7.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
"""
 
2
Copyright (C) 2004 Sandino Flores Moreno
 
3
 
 
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.
 
8
 
 
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.
 
13
 
 
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
 
17
USA
 
18
 
 
19
simplegladeapp.py - Module that provides an object oriented abstraction
 
20
to pygtk and libglade.
 
21
 
 
22
    - Adding `object' as base class to SimpleGladeApp class.
 
23
      by Lincoln de Sousa <lincoln@archlinux-br.org>
 
24
 
 
25
    - Commenting `setlocale' call to avoid problems with languages with
 
26
      sufixes (as pt_BR.utf8) by Lincoln de Sousa <lincoln@archlinux-br.org>
 
27
"""
 
28
 
 
29
from __future__ import absolute_import
 
30
from __future__ import division
 
31
from __future__ import print_function
 
32
 
 
33
import pygtk
 
34
pygtk.require('2.0')
 
35
 
 
36
import os
 
37
import re
 
38
import sys
 
39
 
 
40
import gtk
 
41
import gtk.glade
 
42
import inspect
 
43
import tokenize
 
44
import weakref
 
45
 
 
46
__version__ = "1.0"
 
47
__author__ = 'Sandino "tigrux" Flores-Moreno'
 
48
 
 
49
 
 
50
def bindtextdomain(app_name, locale_dir=None):
 
51
    """
 
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
 
54
    languages.
 
55
 
 
56
    app_name:
 
57
        a domain to look for translations, tipically the name of an application.
 
58
 
 
59
    locale_dir:
 
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.
 
62
    """
 
63
    try:
 
64
        import locale
 
65
        import gettext
 
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
 
76
 
 
77
 
 
78
class SimpleGladeApp(object):
 
79
 
 
80
    def __init__(self, path, root=None, domain=None, **kwargs):
 
81
        """
 
82
        Load a glade file specified by glade_filename, using root as
 
83
        root widget and domain as the domain for translations.
 
84
 
 
85
        If it receives extra named arguments (argname=value), then they are used
 
86
        as attributes of the instance.
 
87
 
 
88
        path:
 
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])
 
92
 
 
93
        root:
 
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.
 
97
 
 
98
        domain:
 
99
            A domain to use for loading translations.
 
100
            If None or ommited, no translation is loaded.
 
101
 
 
102
        **kwargs:
 
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.
 
107
        """
 
108
        if os.path.isfile(path):
 
109
            self.glade_path = path
 
110
        else:
 
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():
 
114
            try:
 
115
                setattr(self, key, weakref.proxy(value))
 
116
            except TypeError:
 
117
                setattr(self, key, value)
 
118
        self.glade = None
 
119
        self.install_custom_handler(self.custom_handler)
 
120
        self.glade = self.create_glade(self.glade_path, root, domain)
 
121
        if root:
 
122
            self.main_widget = self.get_widget(root)
 
123
        else:
 
124
            self.main_widget = None
 
125
        self.normalize_names()
 
126
        self.add_callbacks(self)
 
127
        self.new()
 
128
 
 
129
    def __repr__(self):
 
130
        class_name = self.__class__.__name__
 
131
        if self.main_widget:
 
132
            root = gtk.Widget.get_name(self.main_widget)
 
133
            repr = '%s(path="%s", root="%s")' % (class_name, self.glade_path, root)
 
134
        else:
 
135
            repr = '%s(path="%s")' % (class_name, self.glade_path)
 
136
        return repr
 
137
 
 
138
    def new(self):
 
139
        """
 
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
 
142
        """
 
143
        pass
 
144
 
 
145
    def add_callbacks(self, callbacks_proxy):
 
146
        """
 
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).
 
151
 
 
152
        Methods of classes inheriting from SimpleGladeApp are used as
 
153
        callbacks automatically.
 
154
 
 
155
        callbacks_proxy:
 
156
            an instance with methods as code of callbacks.
 
157
            It means it has methods like on_button1_clicked, on_entry1_activate, etc.
 
158
        """
 
159
        self.glade.signal_autoconnect(callbacks_proxy)
 
160
 
 
161
    def normalize_names(self):
 
162
        """
 
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.
 
166
 
 
167
        It also sets a data "prefixes" with the list of
 
168
        prefixes a widget has for each widget.
 
169
        """
 
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))
 
180
            else:
 
181
                setattr(self, widget_api_name, widget)
 
182
                if prefixes:
 
183
                    gtk.Widget.set_data(widget, "prefixes", prefixes)
 
184
 
 
185
    def add_prefix_actions(self, prefix_actions_proxy):
 
186
        """
 
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.
 
191
 
 
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
 
194
        as argument.
 
195
 
 
196
        prefix_actions_proxy:
 
197
            An instance with methods as prefix actions.
 
198
            It means it has methods like prefix_foo, prefix_bar, etc.
 
199
        """
 
200
        prefix_s = "prefix_"
 
201
        prefix_pos = len(prefix_s)
 
202
 
 
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)
 
206
 
 
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))
 
211
 
 
212
        for widget in self.get_widgets():
 
213
            prefixes = gtk.Widget.get_data(widget, "prefixes")
 
214
            if prefixes:
 
215
                for prefix in prefixes:
 
216
                    if prefix in prefix_actions_d:
 
217
                        prefix_action = prefix_actions_d[prefix]
 
218
                        prefix_action(widget)
 
219
 
 
220
    def custom_handler(self,
 
221
                       glade, function_name, widget_name,
 
222
                       str1, str2, int1, int2):
 
223
        """
 
224
        Generic handler for creating custom widgets, internally used to
 
225
        enable custom widgets (custom widgets of glade).
 
226
 
 
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.
 
230
 
 
231
        Methods of classes inheriting from SimpleGladeApp are used as
 
232
        creation functions automatically.
 
233
 
 
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.
 
236
        """
 
237
        try:
 
238
            handler = getattr(self, function_name)
 
239
            return handler(str1, str2, int1, int2)
 
240
        except AttributeError:
 
241
            return None
 
242
 
 
243
    def gtk_widget_show(self, widget, *args):
 
244
        """
 
245
        Predefined callback.
 
246
        The widget is showed.
 
247
        Equivalent to widget.show()
 
248
        """
 
249
        widget.show()
 
250
 
 
251
    def gtk_widget_hide(self, widget, *args):
 
252
        """
 
253
        Predefined callback.
 
254
        The widget is hidden.
 
255
        Equivalent to widget.hide()
 
256
        """
 
257
        widget.hide()
 
258
        return True
 
259
 
 
260
    def gtk_widget_grab_focus(self, widget, *args):
 
261
        """
 
262
        Predefined callback.
 
263
        The widget grabs the focus.
 
264
        Equivalent to widget.grab_focus()
 
265
        """
 
266
        widget.grab_focus()
 
267
 
 
268
    def gtk_widget_destroy(self, widget, *args):
 
269
        """
 
270
        Predefined callback.
 
271
        The widget is destroyed.
 
272
        Equivalent to widget.destroy()
 
273
        """
 
274
        widget.destroy()
 
275
 
 
276
    def gtk_window_activate_default(self, widget, *args):
 
277
        """
 
278
        Predefined callback.
 
279
        The default widget of the window is activated.
 
280
        Equivalent to window.activate_default()
 
281
        """
 
282
        widget.activate_default()
 
283
 
 
284
    def gtk_true(self, *args):
 
285
        """
 
286
        Predefined callback.
 
287
        Equivalent to return True in a callback.
 
288
        Useful for stopping propagation of signals.
 
289
        """
 
290
        return True
 
291
 
 
292
    def gtk_false(self, *args):
 
293
        """
 
294
        Predefined callback.
 
295
        Equivalent to return False in a callback.
 
296
        """
 
297
        return False
 
298
 
 
299
    def gtk_main_quit(self, *args):
 
300
        """
 
301
        Predefined callback.
 
302
        Equivalent to self.quit()
 
303
        """
 
304
        self.quit()
 
305
 
 
306
    def main(self):
 
307
        """
 
308
        Starts the main loop of processing events.
 
309
        The default implementation calls gtk.main()
 
310
 
 
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()
 
314
 
 
315
        Do not directly call this method in your programs.
 
316
        Use the method run() instead.
 
317
        """
 
318
        gtk.main()
 
319
 
 
320
    def quit(self, *args):
 
321
        """
 
322
        Quit processing events.
 
323
        The default implementation calls gtk.main_quit()
 
324
 
 
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()
 
328
        """
 
329
        gtk.main_quit()
 
330
 
 
331
    def run(self):
 
332
        """
 
333
        Starts the main loop of processing events checking for Control-C.
 
334
 
 
335
        The default implementation checks wheter a Control-C is pressed,
 
336
        then calls on_keyboard_interrupt().
 
337
 
 
338
        Use this method for starting programs.
 
339
        """
 
340
        try:
 
341
            self.main()
 
342
        except KeyboardInterrupt:
 
343
            self.on_keyboard_interrupt()
 
344
 
 
345
    def on_keyboard_interrupt(self):
 
346
        """
 
347
        This method is called by the default implementation of run()
 
348
        after a program is finished by pressing Control-C.
 
349
        """
 
350
        pass
 
351
 
 
352
    def install_custom_handler(self, custom_handler):
 
353
        gtk.glade.set_custom_handler(custom_handler)
 
354
 
 
355
    def create_glade(self, glade_path, root, domain):
 
356
        return gtk.glade.XML(glade_path, root, domain)
 
357
 
 
358
    def get_widget(self, widget_name):
 
359
        return self.glade.get_widget(widget_name)
 
360
 
 
361
    def get_widgets(self):
 
362
        return self.glade.get_widget_prefix("")