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:
parent
5392585893
commit
678057a0d3
@ -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,7 +54,11 @@ if __name__ == '__main__':
|
||||
TERMINATOR = Terminator()
|
||||
TERMINATOR.origcwd = ORIGCWD
|
||||
TERMINATOR.reconfigure()
|
||||
TERMINATOR.new_window()
|
||||
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:
|
||||
import terminatorlib.debugserver as debugserver
|
||||
|
@ -206,8 +206,8 @@ 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
|
||||
|
||||
|
@ -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:
|
||||
|
@ -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:
|
||||
|
@ -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',
|
||||
|
@ -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):
|
||||
|
@ -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"""
|
||||
|
@ -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()
|
||||
|
@ -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:
|
||||
|
@ -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"""
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user