summaryrefslogtreecommitdiff
path: root/trunk/dimbola/gtkapp.py
blob: 81a7d807d1c97b249b85d9cfc99ff0315864f78b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
# Copyright (C) 2009  Lars Wirzenius <liw@liw.fi>
# 
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# 
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
# 
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.


'''Helper class for writing PyGTK applications.'''


import gobject
import gtk


class GtkApplication(object):

    '''Base class for GTK+ applications.
    
    This class provides some convenience functions for GTK+ applications.
    It makes some assumptions to simplify things:
    
    * The UI will be made with Glade and described with a .ui file, 
      using GtkBuilder.
    * A dictionary of all widgets is created as the widgets attribute.
      It is indexed by the name of the widget, as defined in the .ui file.
    * Callbacks will be named on_widgetname_signalname. They will be connected
      automatically if this naming convention is followed.
    * Methods named widgetname_is_sensitive control the sensitivity of
      widgets that need to become sensitive or not based on the state of
      the program.
    * signal callbacks and *_is_sensitive are methods of "controllers",
      which are provided to setup_widgets as an argument, and which it
      stores into the controllers attribute.
    
    '''

    def setup_widgets(self, glade_filename, controllers):
        '''Find all widgets and connect them to signal handlers.
        
        The list of controllers will be stored in the controllers 
        attribute.
        
        '''

        self.controllers = controllers

        if not hasattr(self, 'widgets'):
            self.widgets = {}
        builder = gtk.Builder()
        if builder.add_from_file(glade_filename) == 0:
            raise Exception('GtkBuilder.add_from_file failed for %s' % 
                            glade_filename)
        for widget in builder.get_objects():
            if isinstance(widget, gtk.Widget):
                self.setup_a_widget(widget)

    def setup_a_widget(self, widget):
        name = widget.get_property('name')
        self.widgets[name] = widget
        for controller in self.controllers:
            for attr in dir(controller):
                prefix = 'on_%s_' % name
                if attr.startswith(prefix):
                    signal_name = attr[len(prefix):]
                    method = getattr(controller, attr)
                    widget.connect(signal_name, method)

    def set_sensitive(self):
        '''Set all widgets to be sensitive or not.
        
        The sensitivity of each widget is tested with a method called
        widgetname_is_sensitive. The method must be in one of the controllers
        given to setup_widgets.
        
        You should call this whenever one of the conditions for sensitivity
        changes.
        
        '''
        
        suffix = '_is_sensitive'
        for controller in self.controllers:
            for attrname in dir(controller):
                if attrname.endswith(suffix):
                    widgetname = attrname[:-len(suffix)]
                    if widgetname in self.widgets:
                        widget = self.widgets[widgetname]
                        method = getattr(controller, attrname)
                        widget.set_sensitive(bool(method()))