Rework layout config to flatten and build up trees
This commit is contained in:
parent
9ac5f913fa
commit
1aadbae30b
@ -206,7 +206,16 @@ DEFAULTS = {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
'layouts': {
|
'layouts': {
|
||||||
'default': "{'type': 'Window', 'children': [{'type': 'Terminal'}]}",
|
'default': {
|
||||||
|
'window0': {
|
||||||
|
'type': 'Window',
|
||||||
|
'parent': ''
|
||||||
|
},
|
||||||
|
'child1': {
|
||||||
|
'type': 'Terminal',
|
||||||
|
'parent': 'window0'
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
'plugins': {
|
'plugins': {
|
||||||
},
|
},
|
||||||
@ -381,7 +390,7 @@ class ConfigBase(Borg):
|
|||||||
if self.layouts is None:
|
if self.layouts is None:
|
||||||
self.layouts = {}
|
self.layouts = {}
|
||||||
for layout in DEFAULTS['layouts']:
|
for layout in DEFAULTS['layouts']:
|
||||||
self.layouts[layout] = eval(DEFAULTS['layouts'][layout])
|
self.layouts[layout] = copy(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
|
||||||
@ -433,6 +442,15 @@ class ConfigBase(Borg):
|
|||||||
configspecdata['profiles'] = {}
|
configspecdata['profiles'] = {}
|
||||||
configspecdata['profiles']['__many__'] = section
|
configspecdata['profiles']['__many__'] = section
|
||||||
|
|
||||||
|
section = {}
|
||||||
|
section['type'] = 'string'
|
||||||
|
section['parent'] = 'string'
|
||||||
|
section['profile'] = 'string(default=default)'
|
||||||
|
section['command'] = 'string(default="")'
|
||||||
|
configspecdata['layouts'] = {}
|
||||||
|
configspecdata['layouts']['__many__'] = {}
|
||||||
|
configspecdata['layouts']['__many__']['__many__'] = section
|
||||||
|
|
||||||
configspec = ConfigObj(configspecdata)
|
configspec = ConfigObj(configspecdata)
|
||||||
if DEBUG == True:
|
if DEBUG == True:
|
||||||
configspec.write(open('/tmp/terminator_configspec_debug.txt', 'w'))
|
configspec.write(open('/tmp/terminator_configspec_debug.txt', 'w'))
|
||||||
@ -460,9 +478,11 @@ class ConfigBase(Borg):
|
|||||||
err('ConfigBase::load: config format is not valid')
|
err('ConfigBase::load: config format is not valid')
|
||||||
for (section_list, key, _other) in flatten_errors(parser, result):
|
for (section_list, key, _other) in flatten_errors(parser, result):
|
||||||
if key is not None:
|
if key is not None:
|
||||||
print('[%s]: %s is invalid' % (','.join(section_list), key))
|
err('[%s]: %s is invalid' % (','.join(section_list), key))
|
||||||
else:
|
else:
|
||||||
print ('[%s] missing' % ','.join(section_list))
|
err('[%s] missing' % ','.join(section_list))
|
||||||
|
else:
|
||||||
|
dbg('config validated successfully')
|
||||||
|
|
||||||
for section_name in self.sections:
|
for section_name in self.sections:
|
||||||
dbg('ConfigBase::load: Processing section: %s' % section_name)
|
dbg('ConfigBase::load: Processing section: %s' % section_name)
|
||||||
@ -471,6 +491,7 @@ class ConfigBase(Borg):
|
|||||||
for profile in parser[section_name]:
|
for profile in parser[section_name]:
|
||||||
dbg('ConfigBase::load: Processing profile: %s' % profile)
|
dbg('ConfigBase::load: Processing profile: %s' % profile)
|
||||||
if not section.has_key(section_name):
|
if not section.has_key(section_name):
|
||||||
|
# FIXME: Should this be outside the loop?
|
||||||
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 == 'plugins':
|
elif section_name == 'plugins':
|
||||||
@ -479,17 +500,10 @@ class ConfigBase(Borg):
|
|||||||
part))
|
part))
|
||||||
section[part] = parser[section_name][part]
|
section[part] = parser[section_name][part]
|
||||||
elif section_name == 'layouts':
|
elif section_name == 'layouts':
|
||||||
for part in parser[section_name]:
|
for layout in parser[section_name]:
|
||||||
dbg('ConfigBase::load: Processing %s: %s' % (section_name,
|
dbg('ConfigBase::load: Processing %s: %s' % (section_name,
|
||||||
part))
|
layout))
|
||||||
try:
|
section[layout] = parser[section_name][layout]
|
||||||
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])
|
||||||
@ -519,13 +533,7 @@ 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)
|
||||||
if layout == 'default' and \
|
parser['layouts'][layout] = 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:
|
||||||
|
@ -190,7 +190,7 @@ the %s will also close all terminals within it.') % (reqtype, reqtype))
|
|||||||
|
|
||||||
return(terminals)
|
return(terminals)
|
||||||
|
|
||||||
def describe_layout(self):
|
def describe_layout(self, count, parent, global_layout):
|
||||||
"""Describe our current layout"""
|
"""Describe our current layout"""
|
||||||
layout = {}
|
layout = {}
|
||||||
maker = Factory()
|
maker = Factory()
|
||||||
@ -200,11 +200,16 @@ the %s will also close all terminals within it.') % (reqtype, reqtype))
|
|||||||
return({})
|
return({})
|
||||||
|
|
||||||
layout['type'] = mytype
|
layout['type'] = mytype
|
||||||
layout['children'] = []
|
layout['parent'] = parent
|
||||||
for child in self.get_children():
|
name = 'child%d' % count
|
||||||
layout['children'].append(child.describe_layout())
|
count = count + 1
|
||||||
|
|
||||||
return(layout)
|
global_layout[name] = layout
|
||||||
|
|
||||||
|
for child in self.get_children():
|
||||||
|
count = child.describe_layout(count, name, global_layout)
|
||||||
|
|
||||||
|
return(count)
|
||||||
|
|
||||||
def create_layout(self, layout):
|
def create_layout(self, layout):
|
||||||
"""Apply settings for our layout"""
|
"""Apply settings for our layout"""
|
||||||
|
@ -190,8 +190,9 @@ class Paned(Container):
|
|||||||
err('incorrect number of children for Paned: %s' % layout)
|
err('incorrect number of children for Paned: %s' % layout)
|
||||||
return
|
return
|
||||||
|
|
||||||
for num in xrange(0, 2):
|
num = 0
|
||||||
child = children[num]
|
for child_key in children:
|
||||||
|
child = children[child_key]
|
||||||
if child['type'] == 'Terminal':
|
if child['type'] == 'Terminal':
|
||||||
continue
|
continue
|
||||||
elif child['type'] == 'VPaned':
|
elif child['type'] == 'VPaned':
|
||||||
@ -208,9 +209,12 @@ class Paned(Container):
|
|||||||
self.split_axis(terminal, False)
|
self.split_axis(terminal, False)
|
||||||
else:
|
else:
|
||||||
err('unknown child type: %s' % child['type'])
|
err('unknown child type: %s' % child['type'])
|
||||||
|
num = num + 1
|
||||||
|
|
||||||
self.get_child1().create_layout(children[0])
|
keys = children.keys()
|
||||||
self.get_child2().create_layout(children[1])
|
keys.sort()
|
||||||
|
self.get_child1().create_layout(children[keys[0]])
|
||||||
|
self.get_child2().create_layout(children[keys[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"""
|
||||||
|
@ -1165,11 +1165,15 @@ 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):
|
def describe_layout(self, count, parent, global_layout):
|
||||||
"""Describe our layout"""
|
"""Describe our layout"""
|
||||||
layout = {}
|
layout = {}
|
||||||
layout['type'] = 'Terminal'
|
layout['type'] = 'Terminal'
|
||||||
return(layout)
|
layout['parent'] = parent
|
||||||
|
name = 'terminal%d' % count
|
||||||
|
count = count + 1
|
||||||
|
global_layout[name] = layout
|
||||||
|
return(count)
|
||||||
|
|
||||||
def create_layout(self, layout):
|
def create_layout(self, layout):
|
||||||
"""Apply our layout"""
|
"""Apply our layout"""
|
||||||
|
@ -106,6 +106,7 @@ class Terminator(Borg):
|
|||||||
def create_layout(self, layoutname):
|
def create_layout(self, layoutname):
|
||||||
"""Create all the parts necessary to satisfy the specified layout"""
|
"""Create all the parts necessary to satisfy the specified layout"""
|
||||||
layout = None
|
layout = None
|
||||||
|
objects = {}
|
||||||
|
|
||||||
layout = self.config.layout_get_config(layoutname)
|
layout = self.config.layout_get_config(layoutname)
|
||||||
if not layout:
|
if not layout:
|
||||||
@ -113,12 +114,45 @@ class Terminator(Borg):
|
|||||||
err('layout %s not defined' % layout)
|
err('layout %s not defined' % layout)
|
||||||
raise(KeyError)
|
raise(KeyError)
|
||||||
|
|
||||||
|
# Wind the flat objects into a hierarchy
|
||||||
|
hierarchy = {}
|
||||||
|
count = 0
|
||||||
|
# Loop over the layout until we have consumed it, or hit 1000 loops.
|
||||||
|
# This is a stupid artificial limit, but it's safe.
|
||||||
|
while len(layout) > 0 and count < 1000:
|
||||||
|
count = count + 1
|
||||||
|
if count == 1000:
|
||||||
|
err('hit maximum loop boundary. THIS IS VERY LIKELY A BUG')
|
||||||
|
for obj in layout.keys():
|
||||||
|
if layout[obj]['type'].lower() == 'window':
|
||||||
|
hierarchy[obj] = {}
|
||||||
|
hierarchy[obj]['type'] = 'Window'
|
||||||
|
hierarchy[obj]['children'] = {}
|
||||||
|
objects[obj] = hierarchy[obj]
|
||||||
|
del(layout[obj])
|
||||||
|
else:
|
||||||
|
# Now examine children to see if their parents exist yet
|
||||||
|
if not layout[obj].has_key('parent'):
|
||||||
|
err('Invalid object: %s' % obj)
|
||||||
|
del(layout[obj])
|
||||||
|
continue
|
||||||
|
if objects.has_key(layout[obj]['parent']):
|
||||||
|
# Our parent has been created
|
||||||
|
childobj = {}
|
||||||
|
childobj['type'] = layout[obj]['type']
|
||||||
|
childobj['children'] = {}
|
||||||
|
objects[layout[obj]['parent']]['children'][obj] = childobj
|
||||||
|
objects[obj] = childobj
|
||||||
|
del(layout[obj])
|
||||||
|
|
||||||
|
layout = hierarchy
|
||||||
|
|
||||||
for windef in layout:
|
for windef in layout:
|
||||||
if windef['type'] != 'Window':
|
if layout[windef]['type'] != 'Window':
|
||||||
err('invalid layout format. %s' % layout)
|
err('invalid layout format. %s' % layout)
|
||||||
raise(ValueError)
|
raise(ValueError)
|
||||||
window, terminal = self.new_window()
|
window, terminal = self.new_window()
|
||||||
window.create_layout(windef)
|
window.create_layout(layout[windef])
|
||||||
|
|
||||||
def reconfigure(self):
|
def reconfigure(self):
|
||||||
"""Update configuration for the whole application"""
|
"""Update configuration for the whole application"""
|
||||||
@ -230,9 +264,11 @@ class Terminator(Borg):
|
|||||||
|
|
||||||
def describe_layout(self):
|
def describe_layout(self):
|
||||||
"""Describe our current layout"""
|
"""Describe our current layout"""
|
||||||
layout = []
|
layout = {}
|
||||||
|
count = 0
|
||||||
for window in self.windows:
|
for window in self.windows:
|
||||||
layout.append(window.describe_layout())
|
parent = ''
|
||||||
|
count = window.describe_layout(count, parent, layout)
|
||||||
|
|
||||||
return(layout)
|
return(layout)
|
||||||
|
|
||||||
|
@ -581,12 +581,12 @@ class Window(Container, gtk.Window):
|
|||||||
err('layout describes no children: %s' % layout)
|
err('layout describes no children: %s' % layout)
|
||||||
return
|
return
|
||||||
children = layout['children']
|
children = layout['children']
|
||||||
if len(children) != 1:
|
if len(children) != 1:
|
||||||
# We're a Window, we can only have one child
|
# We're a Window, we can only have one child
|
||||||
err('incorrect number of children for Window: %s' % layout)
|
err('incorrect number of children for Window: %s' % layout)
|
||||||
return
|
return
|
||||||
|
|
||||||
child = children[0]
|
child = children[children.keys()[0]]
|
||||||
terminal = self.get_children()[0]
|
terminal = self.get_children()[0]
|
||||||
if child['type'] == 'VPaned':
|
if child['type'] == 'VPaned':
|
||||||
self.split_axis(terminal, True)
|
self.split_axis(terminal, True)
|
||||||
|
Loading…
Reference in New Issue
Block a user