~ubuntu-branches/ubuntu/saucy/terminator/saucy

« back to all changes in this revision

Viewing changes to terminatorlib/container.py

  • Committer: Bazaar Package Importer
  • Author(s): Nicolas Valcárcel Scerpella (Canonical)
  • Date: 2010-04-07 17:10:31 UTC
  • mfrom: (1.1.7 upstream)
  • Revision ID: james.westby@ubuntu.com-20100407171031-35nsuj0tmbub0bj5
Tags: 0.92-0ubuntu1
* New upstream release
* Remove python-xdg from Recommends. (Closes: #567967)
* Downgrade python-gnome2 to Recommends.
* Update python-gtk2 dependency to (>= 2.14.0)
* Add python-keybinder to Recommends

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#!/usr/bin/python
 
2
# Terminator by Chris Jones <cmsj@tenshu.net>
 
3
# GPL v2 only
 
4
"""container.py - classes necessary to contain Terminal widgets"""
 
5
 
 
6
import gobject
 
7
import gtk
 
8
 
 
9
from factory import Factory
 
10
from config import Config
 
11
from util import dbg, err
 
12
from translation import _
 
13
from signalman import Signalman
 
14
 
 
15
# pylint: disable-msg=R0921
 
16
class Container(object):
 
17
    """Base class for Terminator Containers"""
 
18
 
 
19
    terminator = None
 
20
    immutable = None
 
21
    children = None
 
22
    config = None
 
23
    signals = None
 
24
    signalman = None
 
25
 
 
26
    def __init__(self):
 
27
        """Class initialiser"""
 
28
        self.children = []
 
29
        self.signals = []
 
30
        self.cnxids = Signalman()
 
31
        self.config = Config()
 
32
 
 
33
    def register_signals(self, widget):
 
34
        """Register gobject signals in a way that avoids multiple inheritance"""
 
35
        existing = gobject.signal_list_names(widget)
 
36
        for signal in self.signals:
 
37
            if signal['name'] in existing:
 
38
                dbg('Container:: skipping signal %s for %s, already exists' % (
 
39
                        signal['name'], widget))
 
40
            else:
 
41
                dbg('Container:: registering signal for %s on %s' % 
 
42
                        (signal['name'], widget))
 
43
                try:
 
44
                    gobject.signal_new(signal['name'],
 
45
                                       widget,
 
46
                                       signal['flags'],
 
47
                                       signal['return_type'],
 
48
                                        signal['param_types'])
 
49
                except RuntimeError:
 
50
                    err('Container:: registering signal for %s on %s failed' %
 
51
                            (signal['name'], widget))
 
52
 
 
53
    def connect_child(self, widget, signal, handler, *args):
 
54
        """Register the requested signal and record its connection ID"""
 
55
        self.cnxids.new(widget, signal, handler, *args)
 
56
        return
 
57
 
 
58
    def disconnect_child(self, widget):
 
59
        """De-register the signals for a child"""
 
60
        self.cnxids.remove_widget(widget)
 
61
 
 
62
    def get_offspring(self):
 
63
        """Return a list of direct child widgets, if any"""
 
64
        return(self.children)
 
65
 
 
66
    def split_horiz(self, widget, cwd=None):
 
67
        """Split this container horizontally"""
 
68
        return(self.split_axis(widget, True, cwd))
 
69
 
 
70
    def split_vert(self, widget, cwd=None):
 
71
        """Split this container vertically"""
 
72
        return(self.split_axis(widget, False, cwd))
 
73
 
 
74
    def split_axis(self, widget, vertical=True, cwd=None, sibling=None, siblinglast=None):
 
75
        """Default axis splitter. This should be implemented by subclasses"""
 
76
        raise NotImplementedError('split_axis')
 
77
 
 
78
    def add(self, widget):
 
79
        """Add a widget to the container"""
 
80
        raise NotImplementedError('add')
 
81
 
 
82
    def remove(self, widget):
 
83
        """Remove a widget from the container"""
 
84
        raise NotImplementedError('remove')
 
85
 
 
86
    def hoover(self):
 
87
        """Ensure we still have a reason to exist"""
 
88
        raise NotImplementedError('hoover')
 
89
 
 
90
    def get_children(self):
 
91
        """Return an ordered list of the children of this Container"""
 
92
        raise NotImplementedError('get_children')
 
93
 
 
94
    def closeterm(self, widget):
 
95
        """Handle the closure of a terminal"""
 
96
        try:
 
97
            if self.get_property('term_zoomed'):
 
98
                # We're zoomed, so unzoom and then start closing again
 
99
                dbg('Container::closeterm: terminal zoomed, unzooming')
 
100
                self.unzoom(widget)
 
101
                widget.close()
 
102
                return(True)
 
103
        except TypeError:
 
104
            pass
 
105
 
 
106
        if not self.remove(widget):
 
107
            dbg('Container::closeterm: self.remove() failed for %s' % widget)
 
108
            return(False)
 
109
 
 
110
        self.terminator.deregister_terminal(widget)
 
111
        self.terminator.group_hoover()
 
112
        return(True)
 
113
 
 
114
    def resizeterm(self, widget, keyname):
 
115
        """Handle a keyboard event requesting a terminal resize"""
 
116
        raise NotImplementedError('resizeterm')
 
117
 
 
118
    def toggle_zoom(self, widget, fontscale = False):
 
119
        """Toggle the existing zoom state"""
 
120
        try:
 
121
            if self.get_property('term_zoomed'):
 
122
                self.unzoom(widget)
 
123
            else:
 
124
                self.zoom(widget, fontscale)
 
125
        except TypeError:
 
126
            err('Container::toggle_zoom: %s is unable to handle zooming, for \
 
127
            %s' % (self, widget))
 
128
 
 
129
    def zoom(self, widget, fontscale = False):
 
130
        """Zoom a terminal"""
 
131
        raise NotImplementedError('zoom')
 
132
 
 
133
    def unzoom(self, widget):
 
134
        """Unzoom a terminal"""
 
135
        raise NotImplementedError('unzoom')
 
136
 
 
137
    def construct_confirm_close(self, window, reqtype):
 
138
        """Create a confirmation dialog for closing things"""
 
139
        dialog = gtk.Dialog(_('Close?'), window, gtk.DIALOG_MODAL)
 
140
        dialog.set_has_separator(False)
 
141
        dialog.set_resizable(False)
 
142
    
 
143
        dialog.add_button(gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT)
 
144
        c_all = dialog.add_button(gtk.STOCK_CLOSE, gtk.RESPONSE_ACCEPT)
 
145
        c_all.get_children()[0].get_children()[0].get_children()[1].set_label(
 
146
                _('Close _Terminals'))
 
147
    
 
148
        primary = gtk.Label(_('<big><b>Close multiple terminals?</b></big>'))
 
149
        primary.set_use_markup(True)
 
150
        primary.set_alignment(0, 0.5)
 
151
        secondary = gtk.Label(_('This %s has several terminals open. Closing \
 
152
the %s will also close all terminals within it.') % (reqtype, reqtype))
 
153
        secondary.set_line_wrap(True)
 
154
    
 
155
        labels = gtk.VBox()
 
156
        labels.pack_start(primary, False, False, 6)
 
157
        labels.pack_start(secondary, False, False, 6)
 
158
    
 
159
        image = gtk.image_new_from_stock(gtk.STOCK_DIALOG_WARNING,
 
160
                                         gtk.ICON_SIZE_DIALOG)
 
161
        image.set_alignment(0.5, 0)
 
162
    
 
163
        box = gtk.HBox()
 
164
        box.pack_start(image, False, False, 6)
 
165
        box.pack_start(labels, False, False, 6)
 
166
        dialog.vbox.pack_start(box, False, False, 12)
 
167
    
 
168
        dialog.show_all()
 
169
        return(dialog)
 
170
 
 
171
    def propagate_title_change(self, widget, title):
 
172
        """Pass a title change up the widget stack"""
 
173
        maker = Factory()
 
174
        parent = self.get_parent()
 
175
        title = widget.get_window_title()
 
176
 
 
177
        if maker.isinstance(self, 'Notebook'):
 
178
            self.update_tab_label_text(widget, title)
 
179
        elif maker.isinstance(self, 'Window'):
 
180
            self.title.set_title(widget, title)
 
181
 
 
182
        if maker.isinstance(parent, 'Container'):
 
183
            parent.propagate_title_change(widget, title)
 
184
 
 
185
    def get_visible_terminals(self):
 
186
        """Walk the widget tree to find all of the visible terminals. That is,
 
187
        any terminals which are not hidden in another Notebook pane"""
 
188
        maker = Factory()
 
189
        terminals = {}
 
190
 
 
191
        for child in self.get_offspring():
 
192
            if maker.isinstance(child, 'Terminal'):
 
193
                terminals[child] = child.get_allocation()
 
194
            elif maker.isinstance(child, 'Container'):
 
195
                terminals.update(child.get_visible_terminals())
 
196
            else:
 
197
                err('Unknown child type %s' % type(child))
 
198
 
 
199
        return(terminals)
 
200
 
 
201
    def describe_layout(self, count, parent, global_layout, child_order):
 
202
        """Describe our current layout"""
 
203
        layout = {}
 
204
        maker = Factory()
 
205
        mytype = maker.type(self)
 
206
        if not mytype:
 
207
            err('unable to detemine own type. %s' % self)
 
208
            return({})
 
209
 
 
210
        layout['type'] = mytype
 
211
        layout['parent'] = parent
 
212
        layout['order'] = child_order
 
213
 
 
214
        if hasattr(self, 'get_position'):
 
215
            position = self.get_position()
 
216
            if hasattr(position, '__iter__'):
 
217
                position = ':'.join([str(x) for x in position])
 
218
            layout['position'] = position
 
219
 
 
220
        if hasattr(self, 'get_size'):
 
221
            layout['size'] = self.get_size()
 
222
 
 
223
        name = 'child%d' % count
 
224
        count = count + 1
 
225
 
 
226
        global_layout[name] = layout
 
227
 
 
228
        child_order = 0
 
229
        for child in self.get_children():
 
230
            if hasattr(child, 'describe_layout'):
 
231
                count = child.describe_layout(count, name, global_layout, child_order)
 
232
            child_order = child_order + 1
 
233
 
 
234
        return(count)
 
235
 
 
236
    def create_layout(self, layout):
 
237
        """Apply settings for our layout"""
 
238
        raise NotImplementedError('create_layout')
 
239
 
 
240
# vim: set expandtab ts=4 sw=4: