First run at layout loading, creating, enumerating and saving. It sucks and works poorly at the moment, but here it is

This commit is contained in:
Chris Jones 2010-02-01 12:11:44 +00:00
parent 5392585893
commit 678057a0d3
10 changed files with 202 additions and 29 deletions

View File

@ -43,7 +43,7 @@ import terminatorlib.optionparse
from terminatorlib.terminator import Terminator from terminatorlib.terminator import Terminator
from terminatorlib.factory import Factory from terminatorlib.factory import Factory
from terminatorlib.version import APP_NAME, APP_VERSION from terminatorlib.version import APP_NAME, APP_VERSION
from terminatorlib.util import dbg from terminatorlib.util import dbg, err
if __name__ == '__main__': if __name__ == '__main__':
dbg ("%s starting up, version %s" % (APP_NAME, APP_VERSION)) dbg ("%s starting up, version %s" % (APP_NAME, APP_VERSION))
@ -54,6 +54,10 @@ if __name__ == '__main__':
TERMINATOR = Terminator() TERMINATOR = Terminator()
TERMINATOR.origcwd = ORIGCWD TERMINATOR.origcwd = ORIGCWD
TERMINATOR.reconfigure() TERMINATOR.reconfigure()
try:
TERMINATOR.create_layout(OPTIONS.layout)
except (KeyError,ValueError), ex:
err('layout creation failed, creating a window ("%s")' % ex)
TERMINATOR.new_window() TERMINATOR.new_window()
if OPTIONS.debug > 2: if OPTIONS.debug > 2:

View File

@ -206,7 +206,7 @@ DEFAULTS = {
}, },
}, },
'layouts': { 'layouts': {
'default': {'type': 'Terminal'} 'default': "{'type': 'Window', 'children': [{'type': 'Terminal'}]}",
}, },
'plugins': { 'plugins': {
}, },
@ -266,9 +266,9 @@ class Config(object):
"""List all configured profiles""" """List all configured profiles"""
return(self.base.profiles.keys()) return(self.base.profiles.keys())
def add_layout(self, layout): def add_layout(self, name, layout):
"""Add a new layout""" """Add a new layout"""
return(self.base.add_layout(layout)) return(self.base.add_layout(name, layout))
def del_layout(self, layout): def del_layout(self, layout):
"""Delete a layout""" """Delete a layout"""
@ -335,6 +335,14 @@ class Config(object):
"""Set a whole config tree for a given plugin""" """Set a whole config tree for a given plugin"""
return(self.base.set_plugin(plugin, tree)) return(self.base.set_plugin(plugin, tree))
def layout_get_config(self, layout):
"""Return a layout"""
return(self.base.get_layout(layout))
def layout_set_config(self, layout, tree):
"""Set a layout"""
return(self.base.set_layout(layout, tree))
class ConfigBase(Borg): class ConfigBase(Borg):
"""Class to provide access to our user configuration""" """Class to provide access to our user configuration"""
loaded = None loaded = None
@ -371,7 +379,9 @@ class ConfigBase(Borg):
if self.plugins is None: if self.plugins is None:
self.plugins = {} self.plugins = {}
if self.layouts is None: if self.layouts is None:
self.layouts = copy(DEFAULTS['layouts']) self.layouts = {}
for layout in DEFAULTS['layouts']:
self.layouts[layout] = eval(DEFAULTS['layouts'][layout])
def defaults_to_configspec(self): def defaults_to_configspec(self):
"""Convert our tree of default values into a ConfigObj validation """Convert our tree of default values into a ConfigObj validation
@ -463,11 +473,23 @@ class ConfigBase(Borg):
if not section.has_key(section_name): if not section.has_key(section_name):
section[profile] = copy(DEFAULTS['profiles']['default']) section[profile] = copy(DEFAULTS['profiles']['default'])
section[profile].update(parser[section_name][profile]) section[profile].update(parser[section_name][profile])
elif section_name == ['layouts', 'plugins']: elif section_name == 'plugins':
for part in parser[section_name]: for part in parser[section_name]:
dbg('ConfigBase::load: Processing %s: %s' % (section_name, dbg('ConfigBase::load: Processing %s: %s' % (section_name,
part)) part))
section[part] = parser[section_name][part] section[part] = parser[section_name][part]
elif section_name == 'layouts':
for part in parser[section_name]:
dbg('ConfigBase::load: Processing %s: %s' % (section_name,
part))
try:
windows = []
for window in parser[section_name][part]:
windows.append(eval(window))
section[part] = windows
except Exception, ex:
err('Unable to parse layout: %s (%s: %s)' % (part, ex,
window))
else: else:
try: try:
section.update(parser[section_name]) section.update(parser[section_name])
@ -497,8 +519,13 @@ class ConfigBase(Borg):
parser['layouts'] = {} parser['layouts'] = {}
for layout in self.layouts: for layout in self.layouts:
dbg('ConfigBase::save: Processing layout: %s' % layout) dbg('ConfigBase::save: Processing layout: %s' % layout)
parser['layouts'][layout] = dict_diff( if layout == 'default' and \
DEFAULTS['layouts']['default'], self.layouts[layout]) str(self.layouts[layout]) == DEFAULTS['layouts']['default']:
continue;
parser['layouts'][layout] = []
# FIXME: This look seems pointless and broken
for window in self.layouts[layout]:
parser['layouts'][layout].append(str(self.layouts[layout]))
parser['plugins'] = {} parser['plugins'] = {}
for plugin in self.plugins: for plugin in self.plugins:
@ -568,10 +595,21 @@ class ConfigBase(Borg):
self.profiles[profile] = copy(DEFAULTS['profiles']['default']) self.profiles[profile] = copy(DEFAULTS['profiles']['default'])
return(True) return(True)
def add_layout(self, layout): def add_layout(self, name, layout):
"""Add a new layout""" """Add a new layout"""
if layout in self.layouts: if name in self.layouts:
return(False) return(False)
self.layouts[layout] = {'type': 'Terminal'} self.layouts[name] = layout
return(True) return(True)
def get_layout(self, layout):
"""Return a layout"""
if self.layouts.has_key(layout):
return(self.layouts[layout])
else:
err('layout does not exist: %s' % layout)
def set_layout(self, layout, tree):
"""Set a layout"""
self.layouts[layout] = tree

View File

@ -190,4 +190,24 @@ the %s will also close all terminals within it.') % (reqtype, reqtype))
return(terminals) return(terminals)
def describe_layout(self):
"""Describe our current layout"""
layout = {}
maker = Factory()
mytype = maker.type(self)
if not mytype:
err('unable to detemine own type. %s' % self)
return({})
layout['type'] = mytype
layout['children'] = []
for child in self.get_children():
layout['children'].append(child.describe_layout())
return(layout)
def create_layout(self, layout):
"""Apply settings for our layout"""
raise NotImplementedError('create_layout')
# vim: set expandtab ts=4 sw=4: # vim: set expandtab ts=4 sw=4:

View File

@ -26,6 +26,14 @@ from util import dbg, err
# pylint: disable-msg=W0613 # pylint: disable-msg=W0613
class Factory(Borg): class Factory(Borg):
"""Definition of a class that makes other classes""" """Definition of a class that makes other classes"""
types = {'Terminal': 'terminal',
'VPaned': 'paned',
'HPaned': 'paned',
'Paned': 'paned',
'Notebook': 'notebook',
'Container': 'container',
'Window': 'window'}
def __init__(self): def __init__(self):
"""Class initialiser""" """Class initialiser"""
Borg.__init__(self, self.__class__.__name__) Borg.__init__(self, self.__class__.__name__)
@ -37,28 +45,31 @@ class Factory(Borg):
def isinstance(self, product, classtype): def isinstance(self, product, classtype):
"""Check if a given product is a particular type of object""" """Check if a given product is a particular type of object"""
types = {'Terminal': 'terminal', if classtype in self.types.keys():
'VPaned': 'paned',
'HPaned': 'paned',
'Paned': 'paned',
'Notebook': 'notebook',
'Container': 'container',
'Window': 'window'}
if classtype in types.keys():
# This is quite ugly, but we're importing from the current # This is quite ugly, but we're importing from the current
# directory if that makes sense, otherwise falling back to # directory if that makes sense, otherwise falling back to
# terminatorlib. Someone with real Python skills should fix # terminatorlib. Someone with real Python skills should fix
# this to be less insane. # this to be less insane.
try: try:
module = __import__(types[classtype], None, None, ['']) module = __import__(self.types[classtype], None, None, [''])
except ImportError: except ImportError:
module = __import__('terminatorlib.%s' % types[classtype], module = __import__('terminatorlib.%s' % self.types[classtype],
None, None, ['']) None, None, [''])
return(isinstance(product, getattr(module, classtype))) return(isinstance(product, getattr(module, classtype)))
else: else:
err('Factory::isinstance: unknown class type: %s' % classtype) err('Factory::isinstance: unknown class type: %s' % classtype)
return(False) return(False)
def type(self, product):
"""Determine the type of an object we've previously created"""
for atype in self.types:
# Skip over generic types
if atype in ['Container', 'Paned']:
continue
if self.isinstance(product, atype):
return(atype)
return(None)
def make(self, product, **kwargs): def make(self, product, **kwargs):
"""Make the requested product""" """Make the requested product"""
try: try:

View File

@ -67,6 +67,7 @@ command to execute inside the terminal, and its arguments')
dest='working_directory', help='Set the working directory') dest='working_directory', help='Set the working directory')
parser.add_option('-r', '--role', dest='role', help='Set a custom \ parser.add_option('-r', '--role', dest='role', help='Set a custom \
WM_WINDOW_ROLE property on the window') WM_WINDOW_ROLE property on the window')
parser.add_option('-l', '--layout', dest='layout', help='Select a layout')
for item in ['--sm-client-id', '--sm-config-prefix', '--screen', '-n', for item in ['--sm-client-id', '--sm-config-prefix', '--screen', '-n',
'--no-gconf', '-p', '--profile' ]: '--no-gconf', '-p', '--profile' ]:
parser.add_option(item, dest='dummy', action='store', parser.add_option(item, dest='dummy', action='store',

View File

@ -178,6 +178,40 @@ class Paned(Container):
# This is not a key we can handle # This is not a key we can handle
self.emit('resize-term', keyname) self.emit('resize-term', keyname)
def create_layout(self, layout):
"""Apply layout configuration"""
if not layout.has_key('children'):
err('layout specifies no children: %s' % layout)
return
children = layout['children']
if len(children) != 2:
# Paned widgets can only have two children
err('incorrect number of children for Paned: %s' % layout)
return
for num in xrange(0, 2):
child = children[num]
if child['type'] == 'Terminal':
continue
elif child['type'] == 'VPaned':
if num == 0:
terminal = self.get_child1()
else:
terminal = self.get_child2()
self.split_axis(terminal, True)
elif child['type'] == 'HPaned':
if num == 0:
terminal = self.get_child1()
else:
terminal = self.get_child2()
self.split_axis(terminal, False)
else:
err('unknown child type: %s' % child['type'])
self.get_child1().create_layout(children[0])
self.get_child2().create_layout(children[1])
class HPaned(Paned, gtk.HPaned): class HPaned(Paned, gtk.HPaned):
"""Merge gtk.HPaned into our base Paned Container""" """Merge gtk.HPaned into our base Paned Container"""
def __init__(self): def __init__(self):

View File

@ -662,21 +662,23 @@ class PrefsEditor:
def on_layoutaddbutton_clicked(self, _button): def on_layoutaddbutton_clicked(self, _button):
"""Add a new layout to the list""" """Add a new layout to the list"""
terminator = Terminator()
current_layout = terminator.describe_layout()
guiget = self.builder.get_object guiget = self.builder.get_object
treeview = guiget('layoutlist') treeview = guiget('layoutlist')
model = treeview.get_model() model = treeview.get_model()
values = [ r[0] for r in model ] values = [ r[0] for r in model ]
newlayout = _('New Layout') name = _('New Layout')
if newlayout in values: if name in values:
i = 1 i = 1
while newlayout in values: while name in values:
i = i + 1 i = i + 1
newlayout = '%s %d' % (_('New Layout'), i) name = '%s %d' % (_('New Layout'), i)
if self.config.add_layout(newlayout): if self.config.add_layout(name, current_layout):
model.append([newlayout, True]) model.append([name, True])
def on_layoutremovebutton_clicked(self, _button): def on_layoutremovebutton_clicked(self, _button):
"""Remove a layout from the list""" """Remove a layout from the list"""

View File

@ -1159,6 +1159,16 @@ for %s (%s)' % (name, urlplugin.__class__.__name__))
window = util.get_top_window(self) window = util.get_top_window(self)
window.set_urgency_hint(True) window.set_urgency_hint(True)
def describe_layout(self):
"""Describe our layout"""
layout = {}
layout['type'] = 'Terminal'
return(layout)
def create_layout(self, layout):
"""Apply our layout"""
print "Terminal::create_layout: Unimplemented. %s" % layout
# There now begins a great list of keyboard event handlers # There now begins a great list of keyboard event handlers
def key_zoom_in(self): def key_zoom_in(self):
self.zoom_in() self.zoom_in()

View File

@ -103,6 +103,23 @@ class Terminator(Borg):
return(window, terminal) return(window, terminal)
def create_layout(self, layoutname):
"""Create all the parts necessary to satisfy the specified layout"""
layout = None
layout = self.config.layout_get_config(layoutname)
if not layout:
# User specified a non-existent layout. default to one Terminal
err('layout %s not defined' % layout)
raise(KeyError)
for windef in layout:
if windef['type'] != 'Window':
err('invalid layout format. %s' % layout)
raise(ValueError)
window, terminal = self.new_window()
window.create_layout(windef)
def reconfigure(self): def reconfigure(self):
"""Update configuration for the whole application""" """Update configuration for the whole application"""
@ -210,4 +227,13 @@ class Terminator(Borg):
for terminal in self.terminals: for terminal in self.terminals:
terminal.titlebar.update(widget) terminal.titlebar.update(widget)
return return
def describe_layout(self):
"""Describe our current layout"""
layout = []
for window in self.windows:
layout.append(window.describe_layout())
return(layout)
# vim: set expandtab ts=4 sw=4: # vim: set expandtab ts=4 sw=4:

View File

@ -575,6 +575,33 @@ class Window(Container, gtk.Window):
if next is not None: if next is not None:
terminals[next].grab_focus() terminals[next].grab_focus()
def create_layout(self, layout):
"""Apply any config items from our layout"""
if not layout.has_key('children'):
err('layout describes no children: %s' % layout)
return
children = layout['children']
if len(children) != 1:
# We're a Window, we can only have one child
err('incorrect number of children for Window: %s' % layout)
return
child = children[0]
terminal = self.get_children()[0]
if child['type'] == 'VPaned':
self.split_axis(terminal, True)
elif child['type'] == 'HPaned':
self.split_axis(terminal, False)
elif child['type'] == 'Notebook':
self.tab_new()
elif child['type'] == 'Terminal':
pass
else:
err('unknown child type: %s' % child['type'])
return
self.get_children()[0].create_layout(child)
class WindowTitle(object): class WindowTitle(object):
"""Class to handle the setting of the window title""" """Class to handle the setting of the window title"""