Create a new class Signalman which is used to track the glib signals on a widget since at least two of our classes were doing this themselves. Also integrated it into one of those classes, Container() where it is only used by VPaned and HPaned. Also add doctests for it
This commit is contained in:
parent
8c7218121f
commit
8ad7ac07b1
|
@ -10,6 +10,7 @@ from factory import Factory
|
||||||
from config import Config
|
from config import Config
|
||||||
from util import dbg, err
|
from util import dbg, err
|
||||||
from translation import _
|
from translation import _
|
||||||
|
from signalman import Signalman
|
||||||
|
|
||||||
# pylint: disable-msg=R0921
|
# pylint: disable-msg=R0921
|
||||||
class Container(object):
|
class Container(object):
|
||||||
|
@ -20,13 +21,13 @@ class Container(object):
|
||||||
children = None
|
children = None
|
||||||
config = None
|
config = None
|
||||||
signals = None
|
signals = None
|
||||||
cnxids = None
|
signalman = None
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
"""Class initialiser"""
|
"""Class initialiser"""
|
||||||
self.children = []
|
self.children = []
|
||||||
self.signals = []
|
self.signals = []
|
||||||
self.cnxids = {}
|
self.cnxids = Signalman()
|
||||||
self.config = Config()
|
self.config = Config()
|
||||||
|
|
||||||
def register_signals(self, widget):
|
def register_signals(self, widget):
|
||||||
|
@ -49,28 +50,14 @@ class Container(object):
|
||||||
err('Container:: registering signal for %s on %s failed' %
|
err('Container:: registering signal for %s on %s failed' %
|
||||||
(signal['name'], widget))
|
(signal['name'], widget))
|
||||||
|
|
||||||
def connect_child(self, widget, signal, handler, data=None):
|
def connect_child(self, widget, signal, handler, *args):
|
||||||
"""Register the requested signal and record its connection ID"""
|
"""Register the requested signal and record its connection ID"""
|
||||||
if not self.cnxids.has_key(widget):
|
self.cnxids.new(widget, signal, handler, *args)
|
||||||
self.cnxids[widget] = []
|
return
|
||||||
|
|
||||||
if data is not None:
|
|
||||||
self.cnxids[widget].append(widget.connect(signal, handler, data))
|
|
||||||
dbg('Container::connect_child: connecting %s(%s) for %s::%s' %
|
|
||||||
(handler.__name__, data, widget.__class__.__name__, signal))
|
|
||||||
else:
|
|
||||||
self.cnxids[widget].append(widget.connect(signal, handler))
|
|
||||||
dbg('Container::connect_child: registering %s to handle %s::%s' %
|
|
||||||
(handler.__name__, widget.__class__.__name__, signal))
|
|
||||||
|
|
||||||
def disconnect_child(self, widget):
|
def disconnect_child(self, widget):
|
||||||
"""De-register the signals for a child"""
|
"""De-register the signals for a child"""
|
||||||
if self.cnxids.has_key(widget):
|
self.cnxids.remove_widget(widget)
|
||||||
for cnxid in self.cnxids[widget]:
|
|
||||||
dbg('Container::disconnect_child: removing handler on %s' %
|
|
||||||
type(widget))
|
|
||||||
widget.disconnect(cnxid)
|
|
||||||
del(self.cnxids[widget])
|
|
||||||
|
|
||||||
def get_offspring(self):
|
def get_offspring(self):
|
||||||
"""Return a list of child widgets, if any"""
|
"""Return a list of child widgets, if any"""
|
||||||
|
|
|
@ -37,8 +37,7 @@ class Paned(Container):
|
||||||
|
|
||||||
dbg("Paned::set_initial_position: Setting position to: %d" % position)
|
dbg("Paned::set_initial_position: Setting position to: %d" % position)
|
||||||
self.set_position(position)
|
self.set_position(position)
|
||||||
self.disconnect(self.cnxids['init'])
|
self.cnxids.remove_signal(self, 'expose-event')
|
||||||
del(self.cnxids['init'])
|
|
||||||
|
|
||||||
# pylint: disable-msg=W0613
|
# pylint: disable-msg=W0613
|
||||||
def split_axis(self, widget, vertical=True, sibling=None):
|
def split_axis(self, widget, vertical=True, sibling=None):
|
||||||
|
@ -78,7 +77,6 @@ class Paned(Container):
|
||||||
else:
|
else:
|
||||||
raise ValueError('Paned widgets can only have two children')
|
raise ValueError('Paned widgets can only have two children')
|
||||||
|
|
||||||
self.cnxids[widget] = []
|
|
||||||
if maker.isinstance(widget, 'Terminal'):
|
if maker.isinstance(widget, 'Terminal'):
|
||||||
top_window = get_top_window(self)
|
top_window = get_top_window(self)
|
||||||
|
|
||||||
|
@ -92,8 +90,7 @@ class Paned(Container):
|
||||||
for signal in signals:
|
for signal in signals:
|
||||||
self.connect_child(widget, signal, signals[signal])
|
self.connect_child(widget, signal, signals[signal])
|
||||||
|
|
||||||
self.connect_child(widget, 'maximise', top_window.zoom,
|
self.connect_child(widget, 'maximise', top_window.zoom, False)
|
||||||
False)
|
|
||||||
|
|
||||||
widget.grab_focus()
|
widget.grab_focus()
|
||||||
|
|
||||||
|
@ -176,8 +173,7 @@ class HPaned(Paned, gtk.HPaned):
|
||||||
Paned.__init__(self)
|
Paned.__init__(self)
|
||||||
gtk.HPaned.__init__(self)
|
gtk.HPaned.__init__(self)
|
||||||
self.register_signals(HPaned)
|
self.register_signals(HPaned)
|
||||||
self.cnxids['init'] = self.connect('expose-event',
|
self.cnxids.new(self, 'expose-event', self.set_initial_position)
|
||||||
self.set_initial_position)
|
|
||||||
|
|
||||||
class VPaned(Paned, gtk.VPaned):
|
class VPaned(Paned, gtk.VPaned):
|
||||||
"""Merge gtk.VPaned into our base Paned Container"""
|
"""Merge gtk.VPaned into our base Paned Container"""
|
||||||
|
@ -186,8 +182,7 @@ class VPaned(Paned, gtk.VPaned):
|
||||||
Paned.__init__(self)
|
Paned.__init__(self)
|
||||||
gtk.VPaned.__init__(self)
|
gtk.VPaned.__init__(self)
|
||||||
self.register_signals(VPaned)
|
self.register_signals(VPaned)
|
||||||
self.cnxids['init'] = self.connect('expose-event',
|
self.cnxids.new(self, 'expose-event', self.set_initial_position)
|
||||||
self.set_initial_position)
|
|
||||||
|
|
||||||
gobject.type_register(HPaned)
|
gobject.type_register(HPaned)
|
||||||
gobject.type_register(VPaned)
|
gobject.type_register(VPaned)
|
||||||
|
|
|
@ -0,0 +1,54 @@
|
||||||
|
#!/usr/bin/python
|
||||||
|
# Terminator by Chris Jones <cmsj@tenshu.net>
|
||||||
|
# GPL v2 only
|
||||||
|
"""signalman.py - class providing a glib signal tracker"""
|
||||||
|
|
||||||
|
from util import dbg, err
|
||||||
|
|
||||||
|
class Signalman(object):
|
||||||
|
"""Class providing glib signal tracking and management"""
|
||||||
|
|
||||||
|
cnxids = None
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
"""Class initialiser"""
|
||||||
|
self.cnxids = {}
|
||||||
|
|
||||||
|
def __del__(self):
|
||||||
|
"""Class destructor"""
|
||||||
|
if len(self.cnxids.keys()) > 0:
|
||||||
|
err('Signals remain. This is likely a bug: %s' % self.cnxids)
|
||||||
|
|
||||||
|
def new(self, widget, signal, handler, *args):
|
||||||
|
"""Register a new signal on a widget"""
|
||||||
|
if not self.cnxids.has_key(widget):
|
||||||
|
dbg('creating new bucket for %s' % type(widget))
|
||||||
|
self.cnxids[widget] = {}
|
||||||
|
|
||||||
|
if self.cnxids[widget].has_key(signal):
|
||||||
|
err('%s already has a handler for %s' % (id(widget), signal))
|
||||||
|
|
||||||
|
self.cnxids[widget][signal] = widget.connect(signal, handler, *args)
|
||||||
|
dbg('connected %s::%s to %s' % (type(widget), signal, handler))
|
||||||
|
|
||||||
|
def remove_signal(self, widget, signal):
|
||||||
|
"""Remove a signal handler"""
|
||||||
|
if not self.cnxids[widget].has_key(signal):
|
||||||
|
err('%s not registered for %s' % (signal, type(widget)))
|
||||||
|
return
|
||||||
|
dbg('removing %s::%s' % (type(widget), signal))
|
||||||
|
widget.disconnect(self.cnxids[widget][signal])
|
||||||
|
del(self.cnxids[widget][signal])
|
||||||
|
if len(self.cnxids[widget].keys()) == 0:
|
||||||
|
dbg('no more signals for widget')
|
||||||
|
del(self.cnxids[widget])
|
||||||
|
|
||||||
|
def remove_widget(self, widget):
|
||||||
|
"""Remove all signal handlers for a widget"""
|
||||||
|
if not self.cnxids.has_key(widget):
|
||||||
|
dbg('%s not registered' % widget)
|
||||||
|
return
|
||||||
|
signals = self.cnxids[widget].keys()
|
||||||
|
for signal in signals:
|
||||||
|
self.remove_signal(widget, signal)
|
||||||
|
|
|
@ -97,6 +97,7 @@ class Terminal(gtk.VBox):
|
||||||
self.connect('focus-in', self.terminator.focus_changed)
|
self.connect('focus-in', self.terminator.focus_changed)
|
||||||
|
|
||||||
self.matches = {}
|
self.matches = {}
|
||||||
|
# FIXME: Port cnxids to using Signalman
|
||||||
self.cnxids = {}
|
self.cnxids = {}
|
||||||
|
|
||||||
self.config = Config()
|
self.config = Config()
|
||||||
|
|
|
@ -11,6 +11,7 @@ def test_suite():
|
||||||
'cwd',
|
'cwd',
|
||||||
'factory',
|
'factory',
|
||||||
'util',
|
'util',
|
||||||
|
'testsignalman',
|
||||||
):
|
):
|
||||||
suite.addTest(DocTestSuite('terminatorlib.' + name))
|
suite.addTest(DocTestSuite('terminatorlib.' + name))
|
||||||
return suite
|
return suite
|
||||||
|
|
|
@ -0,0 +1,56 @@
|
||||||
|
#!/usr/bin/python
|
||||||
|
# Terminator by Chris Jones <cmsj@tenshu.net>
|
||||||
|
# GPL v2 only
|
||||||
|
"""testsignalman.py - Test the signalman class
|
||||||
|
|
||||||
|
>>> widget = TestWidget()
|
||||||
|
>>> signalman = Signalman()
|
||||||
|
>>> signalman.new(widget, 'test1', handler)
|
||||||
|
>>> signalman.cnxids[widget].keys()
|
||||||
|
['test1']
|
||||||
|
>>> widget.signals.values()
|
||||||
|
['test1']
|
||||||
|
>>> signalman.remove_widget(widget)
|
||||||
|
>>> signalman.cnxids.has_key(widget)
|
||||||
|
False
|
||||||
|
>>> widget.signals.values()
|
||||||
|
[]
|
||||||
|
>>> signalman.new(widget, 'test2', handler)
|
||||||
|
>>> signalman.new(widget, 'test3', handler)
|
||||||
|
>>> signalman.remove_signal(widget, 'test2')
|
||||||
|
>>> signalman.cnxids[widget].keys()
|
||||||
|
['test3']
|
||||||
|
>>> widget.signals.values()
|
||||||
|
['test3']
|
||||||
|
>>> signalman.remove_widget(widget)
|
||||||
|
>>>
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
from signalman import Signalman
|
||||||
|
|
||||||
|
class TestWidget():
|
||||||
|
signals = None
|
||||||
|
count = None
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self.signals = {}
|
||||||
|
self.count = 0
|
||||||
|
|
||||||
|
def connect(self, signal, handler, *args):
|
||||||
|
self.count = self.count + 1
|
||||||
|
self.signals[self.count] = signal
|
||||||
|
return(self.count)
|
||||||
|
|
||||||
|
def disconnect(self, signalid):
|
||||||
|
del(self.signals[signalid])
|
||||||
|
|
||||||
|
def handler():
|
||||||
|
print "I am a test handler"
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
import sys
|
||||||
|
import doctest
|
||||||
|
(failed, attempted) = doctest.testmod()
|
||||||
|
print "%d/%d tests failed" % (failed, attempted)
|
||||||
|
sys.exit(failed)
|
Loading…
Reference in New Issue