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

View File

@ -206,7 +206,7 @@ DEFAULTS = {
},
},
'layouts': {
'default': {'type': 'Terminal'}
'default': "{'type': 'Window', 'children': [{'type': 'Terminal'}]}",
},
'plugins': {
},
@ -266,9 +266,9 @@ class Config(object):
"""List all configured profiles"""
return(self.base.profiles.keys())
def add_layout(self, layout):
def add_layout(self, name, layout):
"""Add a new layout"""
return(self.base.add_layout(layout))
return(self.base.add_layout(name, layout))
def del_layout(self, layout):
"""Delete a layout"""
@ -335,6 +335,14 @@ class Config(object):
"""Set a whole config tree for a given plugin"""
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 to provide access to our user configuration"""
loaded = None
@ -371,7 +379,9 @@ class ConfigBase(Borg):
if self.plugins is None:
self.plugins = {}
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):
"""Convert our tree of default values into a ConfigObj validation
@ -463,11 +473,23 @@ class ConfigBase(Borg):
if not section.has_key(section_name):
section[profile] = copy(DEFAULTS['profiles']['default'])
section[profile].update(parser[section_name][profile])
elif section_name == ['layouts', 'plugins']:
elif section_name == 'plugins':
for part in parser[section_name]:
dbg('ConfigBase::load: Processing %s: %s' % (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:
try:
section.update(parser[section_name])
@ -497,8 +519,13 @@ class ConfigBase(Borg):
parser['layouts'] = {}
for layout in self.layouts:
dbg('ConfigBase::save: Processing layout: %s' % layout)
parser['layouts'][layout] = dict_diff(
DEFAULTS['layouts']['default'], self.layouts[layout])
if layout == 'default' and \
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'] = {}
for plugin in self.plugins:
@ -568,10 +595,21 @@ class ConfigBase(Borg):
self.profiles[profile] = copy(DEFAULTS['profiles']['default'])
return(True)
def add_layout(self, layout):
def add_layout(self, name, layout):
"""Add a new layout"""
if layout in self.layouts:
if name in self.layouts:
return(False)
self.layouts[layout] = {'type': 'Terminal'}
self.layouts[name] = layout
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)
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:

View File

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

View File

@ -67,6 +67,7 @@ command to execute inside the terminal, and its arguments')
dest='working_directory', help='Set the working directory')
parser.add_option('-r', '--role', dest='role', help='Set a custom \
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',
'--no-gconf', '-p', '--profile' ]:
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
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):
"""Merge gtk.HPaned into our base Paned Container"""
def __init__(self):

View File

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

View File

@ -103,6 +103,23 @@ class Terminator(Borg):
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):
"""Update configuration for the whole application"""
@ -210,4 +227,13 @@ class Terminator(Borg):
for terminal in self.terminals:
terminal.titlebar.update(widget)
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:

View File

@ -575,6 +575,33 @@ class Window(Container, gtk.Window):
if next is not None:
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 to handle the setting of the window title"""