~vorlon/ubuntu/saucy/gourmet/trunk

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
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
#!/usr/bin/env python
import gtk.glade, gtk
from gourmet.gdebug import *
from gettext import gettext as _
from gettext import ngettext

# Here we have some classes that implement ActionGroups. This is
# somewhat ugly, but we're designing our interface in glade (which
# doesn't understand ActionGroups) and we still want to use this
# feature -- which lets us automatically associate multiple widgets
# with an action and have things like toggles just work.

class ActionTwoPointFourCompatability:
    """Provide functions that pygtk 2.4 fails to provide for the
    ActionGroup class.

    This class should be inherited from AFTER gtk.Action so that if
    the proper functions are available (i.e. > pygtk 2.6, we won't use
    these at all.
    """
    def set_visible (self, value):
        for w in self.get_proxies():
            if hasattr(w,'set_visible'): w.set_visible(value)

    def get_visible (self):
        for w in self.get_proxies():
            if hasattr(w,'get_visible'): return w.get_visible()

    def set_sensitive (self, value):
        for w in self.get_proxies():
            if hasattr(w,'set_sensitive'): w.set_sensitive(value)

    def get_sensitive (self):
        for w in self.get_proxies():
            if hasattr(w,'get_sensitive'): return w.get_sensitive()


class ToggleActionWithSeparators (gtk.ToggleAction,ActionTwoPointFourCompatability):
    """Create a ToggleAction which can include some separators.

    This allows us to make separators become visible/invisible in sync
    with controls for an action.
    
    This is much worse than the default UIManager way of handling
    separators automatically, but it works with glade as it is made at
    the moment.
    """
    def __init__ (self, *args, **kwargs):
        self.separators = []
        gtk.ToggleAction.__init__(self,*args,**kwargs)

    def add_separator (self, separator_widget):
        self.separators.append(separator_widget)

    def set_visible (self, *args, **kwargs):
        gtk.ToggleAction.set_visible(self,*args,**kwargs)
        if self.is_visible():
            for s in self.separators: s.set_visible(True)
        else:
            for s in self.separators: s.set_visible(False)
            
class ActionWithSeparators (gtk.Action,ActionTwoPointFourCompatability):
    """Create an Action which can include some separators.

    This allows us to make separators become visible/invisible in sync
    with controls for an action.

    This is much worse than the default UIManager way of handling
    separators automatically, but it works with glade as it is made at
    the moment.
    """
    def __init__ (self, *args, **kwargs):
        self.separators = []
        gtk.Action.__init__(self,*args,**kwargs)

    def add_separator (self, separator_widget):
        self.separators.append(separator_widget)

    def set_visible (self, *args, **kwargs):
        gtk.Action.set_visible(self,*args,**kwargs)
        if self.is_visible():
            for s in self.separators: s.set_visible(True)
        else:
            for s in self.separators: s.set_visible(False)

class ActionGroupWithSeparators (gtk.ActionGroup,ActionTwoPointFourCompatability):
    """Create an ActionGroup which can include some separators.

    This allows us to make separators become visible/invisible in sync
    with controls for an action.

    This is much worse than the default UIManager way of handling
    separators automatically, but it works with glade as it is made at
    the moment.
    """
    def __init__ (self, *args, **kwargs):
        self.separators = []
        gtk.ActionGroup.__init__(self,*args,**kwargs)

    def add_separator (self, separator_widget):
        self.separators.append(separator_widget)

    def set_visible (self, visible):
        gtk.ActionGroup.set_visible(self,visible)
        for s in self.separators:
            try:
                s.set_property('visible',visible)
            except:
                debug('no widget %s'%s,5)

class ActionManager:
    """This is a class to handle all Actions for a GUI

    This can be conveniently subclassed by any class handling the main
    GUI interactions.

    This class is made to be the glue between traditional glade and
    ActionManager kung-fu.
    """
    
    def __init__ (self, gladeobj, groups, callbacks):
        """Set up our ActionManager.

        gladeobj - Our route to glade stuff (created by
                   gtk.glade.XML('/path/to/glade')

        groups - a dictionary of group names and actions within them
                 actions are rather complicated...

                 actions are also dictionaries.
                 {'actionName' : [{'tooltip':...,'label':...,...},
                                  ['widgetName','widgetName','widgetName'...]
                                  ]},

                 If parameters 'label', 'stock-id' are not provided,
                 we will attempt to grab them from the first widget using methods
                 get_label() and  get_stock_id(). If we are unable, we will throw
                 an error, because you really do need a label. The solution is to
                 provide the label, or make the first widget in your list one that
                 supports these methods.
                 
        callbacks - an alist of action names and callbacks to be
                    called when the action is activated.
        """
        self.gladeobj = gladeobj
        self.groups = groups
        self.callbacks = callbacks
        self.action_groups = [self.init_group(gname, actions) for gname,actions in self.groups.items()]
        self.make_connections()

    def init_group (self, name, actions):
        setattr(self,name,ActionGroupWithSeparators(name))
        for a in actions:
            for n,ainfo in a.items():
                params,widgets = ainfo
                widg=None
                if not params.has_key('label'):
                    if not widg: widg = self.gladeobj.get_widget(widgets[0])
                    if not widg: raise "Can't find widget %s"%widgets[0]
                    label = widg.get_label()
                    params['label']=label
                if not params.has_key('stock-id'):
                    if not widg: widg = self.gladeobj.get_widget(widgets[0])
                    if not widg: raise "Can't find widget %s"%widgets[0]
                    stockid = widg.get_stock_id()
                    params['stock-id']=stockid
                if not params.has_key('tooltip'):
                    params['tooltip']=''
                widg = self.gladeobj.get_widget(widgets[0])
                try:
                    temp_connection=widg.connect('toggled',lambda *args: False)
                    widg.disconnect(temp_connection)                    
                except TypeError: #unknown signal name (i.e. not a toggle)
                    act = ActionWithSeparators(n,params['label'],params['tooltip'],params['stock-id'])
                else:
                    act = ToggleActionWithSeparators(n,params['label'],params['tooltip'],params['stock-id'])
                if params.has_key('separators'):
                    if type(params['separators']==str): params['separators']=[params['separators']]
                    act.separators=[self.gladeobj.get_widget(w) for w in params['separators']]
                    getattr(self,name).separators.extend(act.separators)
                for w in widgets:
                    ww = self.gladeobj.get_widget(w)
                    if ww:
                        act.connect_proxy(ww)
                    else:
                        debug('Widget %s does not exist!'%w,0)
                # create action as an attribute
                setattr(self,n,act)
                # attach to our ActionGroup                
                getattr(self,name).add_action(act)
        return getattr(self,name)

    def make_connections (self):
        for a,cb in self.callbacks:
            debug('connecting %s activate to %s'%(a,cb),5)
            getattr(self,a).connect('activate',cb)