Add layout save and load of active term for tabs, remember active term on switching tabs, plus more. Too inter-dependant to split into smaller commits.
This commit is contained in:
parent
0272c78739
commit
581b6eeb92
|
@ -275,11 +275,14 @@ the %s will also close all terminals within it.') % (reqtype, reqtype))
|
||||||
|
|
||||||
if mytype == 'Notebook':
|
if mytype == 'Notebook':
|
||||||
labels = []
|
labels = []
|
||||||
|
last_active_term = []
|
||||||
for tabnum in xrange(0, self.get_n_pages()):
|
for tabnum in xrange(0, self.get_n_pages()):
|
||||||
page = self.get_nth_page(tabnum)
|
page = self.get_nth_page(tabnum)
|
||||||
label = self.get_tab_label(page)
|
label = self.get_tab_label(page)
|
||||||
labels.append(label.get_custom_label())
|
labels.append(label.get_custom_label())
|
||||||
|
last_active_term.append(self.last_active_term[self.get_nth_page(tabnum)])
|
||||||
layout['labels'] = labels
|
layout['labels'] = labels
|
||||||
|
layout['last_active_term'] = last_active_term
|
||||||
layout['active_page'] = self.get_current_page()
|
layout['active_page'] = self.get_current_page()
|
||||||
else:
|
else:
|
||||||
if hasattr(self, 'last_active_term') and self.last_active_term is not None:
|
if hasattr(self, 'last_active_term') and self.last_active_term is not None:
|
||||||
|
|
|
@ -12,11 +12,14 @@ from factory import Factory
|
||||||
from container import Container
|
from container import Container
|
||||||
from editablelabel import EditableLabel
|
from editablelabel import EditableLabel
|
||||||
from translation import _
|
from translation import _
|
||||||
from util import err, dbg, enumerate_descendants
|
from util import err, dbg, enumerate_descendants, make_uuid
|
||||||
|
|
||||||
class Notebook(Container, gtk.Notebook):
|
class Notebook(Container, gtk.Notebook):
|
||||||
"""Class implementing a gtk.Notebook container"""
|
"""Class implementing a gtk.Notebook container"""
|
||||||
window = None
|
window = None
|
||||||
|
last_active_term = None
|
||||||
|
pending_on_tab_switch = None
|
||||||
|
pending_on_tab_switch_args = None
|
||||||
|
|
||||||
def __init__(self, window):
|
def __init__(self, window):
|
||||||
"""Class initialiser"""
|
"""Class initialiser"""
|
||||||
|
@ -30,12 +33,16 @@ class Notebook(Container, gtk.Notebook):
|
||||||
self.window = window
|
self.window = window
|
||||||
gobject.type_register(Notebook)
|
gobject.type_register(Notebook)
|
||||||
self.register_signals(Notebook)
|
self.register_signals(Notebook)
|
||||||
|
self.connect('switch-page', self.deferred_on_tab_switch)
|
||||||
self.configure()
|
self.configure()
|
||||||
|
|
||||||
child = window.get_child()
|
child = window.get_child()
|
||||||
window.remove(child)
|
window.remove(child)
|
||||||
window.add(self)
|
window.add(self)
|
||||||
self.newtab(widget=child)
|
self.newtab(widget=child)
|
||||||
|
if window.last_active_term:
|
||||||
|
self.set_last_active_term(window.last_active_term)
|
||||||
|
window.last_active_term = None
|
||||||
|
|
||||||
self.show_all()
|
self.show_all()
|
||||||
|
|
||||||
|
@ -63,6 +70,7 @@ class Notebook(Container, gtk.Notebook):
|
||||||
style.xthickness = 0
|
style.xthickness = 0
|
||||||
style.ythickness = 0
|
style.ythickness = 0
|
||||||
self.modify_style(style)
|
self.modify_style(style)
|
||||||
|
self.last_active_term = {}
|
||||||
|
|
||||||
def create_layout(self, layout):
|
def create_layout(self, layout):
|
||||||
"""Apply layout configuration"""
|
"""Apply layout configuration"""
|
||||||
|
@ -117,10 +125,14 @@ class Notebook(Container, gtk.Notebook):
|
||||||
label = self.get_tab_label(page)
|
label = self.get_tab_label(page)
|
||||||
label.set_custom_label(labeltext)
|
label.set_custom_label(labeltext)
|
||||||
page.create_layout(children[child_key])
|
page.create_layout(children[child_key])
|
||||||
|
|
||||||
|
if layout.get('last_active_term', None):
|
||||||
|
self.last_active_term[page] = make_uuid(layout['last_active_term'][num])
|
||||||
num = num + 1
|
num = num + 1
|
||||||
|
|
||||||
if layout.has_key('active_page'):
|
if layout.has_key('active_page'):
|
||||||
self.set_current_page(int(layout['active_page']))
|
# Need to do it later, or layout changes result
|
||||||
|
gobject.idle_add(self.set_current_page, int(layout['active_page']))
|
||||||
else:
|
else:
|
||||||
self.set_current_page(0)
|
self.set_current_page(0)
|
||||||
|
|
||||||
|
@ -167,12 +179,13 @@ class Notebook(Container, gtk.Notebook):
|
||||||
self.set_current_page(page_num)
|
self.set_current_page(page_num)
|
||||||
|
|
||||||
self.show_all()
|
self.show_all()
|
||||||
terminal.grab_focus()
|
|
||||||
|
|
||||||
while gtk.events_pending():
|
while gtk.events_pending():
|
||||||
gtk.main_iteration_do(False)
|
gtk.main_iteration_do(False)
|
||||||
self.get_toplevel().set_pos_by_ratio = False
|
self.get_toplevel().set_pos_by_ratio = False
|
||||||
|
|
||||||
|
gobject.idle_add(terminal.ensure_visible_and_focussed)
|
||||||
|
|
||||||
def add(self, widget, metadata=None):
|
def add(self, widget, metadata=None):
|
||||||
"""Add a widget to the container"""
|
"""Add a widget to the container"""
|
||||||
dbg('adding a new tab')
|
dbg('adding a new tab')
|
||||||
|
@ -268,15 +281,22 @@ class Notebook(Container, gtk.Notebook):
|
||||||
|
|
||||||
dbg('inserting page at position: %s' % tabpos)
|
dbg('inserting page at position: %s' % tabpos)
|
||||||
self.insert_page(widget, None, tabpos)
|
self.insert_page(widget, None, tabpos)
|
||||||
self.set_tab_label(widget, label)
|
child_widgets = [widget]
|
||||||
self.set_tab_label_packing(widget, not self.config['scroll_tabbar'],
|
child_widgets .extend(enumerate_descendants(widget))
|
||||||
not self.config['scroll_tabbar'],
|
term_widget = None
|
||||||
gtk.PACK_START)
|
for term_widget in child_widgets:
|
||||||
|
if maker.isinstance(term_widget, 'Terminal'):
|
||||||
|
self.set_last_active_term(term_widget.uuid)
|
||||||
|
self.set_tab_label(term_widget, label)
|
||||||
|
self.set_tab_label_packing(term_widget, not self.config['scroll_tabbar'],
|
||||||
|
not self.config['scroll_tabbar'],
|
||||||
|
gtk.PACK_START)
|
||||||
|
break
|
||||||
|
|
||||||
self.set_tab_reorderable(widget, True)
|
self.set_tab_reorderable(widget, True)
|
||||||
self.set_current_page(tabpos)
|
self.set_current_page(tabpos)
|
||||||
self.show_all()
|
self.show_all()
|
||||||
if maker.isinstance(widget, 'Terminal'):
|
if maker.isinstance(term_widget, 'Terminal'):
|
||||||
widget.grab_focus()
|
widget.grab_focus()
|
||||||
|
|
||||||
def wrapcloseterm(self, widget):
|
def wrapcloseterm(self, widget):
|
||||||
|
@ -311,6 +331,7 @@ class Notebook(Container, gtk.Notebook):
|
||||||
|
|
||||||
if maker.isinstance(child, 'Terminal'):
|
if maker.isinstance(child, 'Terminal'):
|
||||||
dbg('Notebook::closetab: child is a single Terminal')
|
dbg('Notebook::closetab: child is a single Terminal')
|
||||||
|
del nb.last_active_term[child]
|
||||||
child.close()
|
child.close()
|
||||||
# FIXME: We only do this del and return here to avoid removing the
|
# FIXME: We only do this del and return here to avoid removing the
|
||||||
# page below, which child.close() implicitly does
|
# page below, which child.close() implicitly does
|
||||||
|
@ -318,9 +339,7 @@ class Notebook(Container, gtk.Notebook):
|
||||||
return
|
return
|
||||||
elif maker.isinstance(child, 'Container'):
|
elif maker.isinstance(child, 'Container'):
|
||||||
dbg('Notebook::closetab: child is a Container')
|
dbg('Notebook::closetab: child is a Container')
|
||||||
dialog = self.construct_confirm_close(self.window, _('tab'))
|
result = self.construct_confirm_close(self.window, _('tab'))
|
||||||
result = dialog.run()
|
|
||||||
dialog.destroy()
|
|
||||||
|
|
||||||
if result == gtk.RESPONSE_ACCEPT:
|
if result == gtk.RESPONSE_ACCEPT:
|
||||||
containers = None
|
containers = None
|
||||||
|
@ -340,9 +359,6 @@ class Notebook(Container, gtk.Notebook):
|
||||||
err('Notebook::closetab: child is unknown type %s' % child)
|
err('Notebook::closetab: child is unknown type %s' % child)
|
||||||
return
|
return
|
||||||
|
|
||||||
nb.remove_page(tabnum)
|
|
||||||
del(label)
|
|
||||||
|
|
||||||
def resizeterm(self, widget, keyname):
|
def resizeterm(self, widget, keyname):
|
||||||
"""Handle a keyboard event requesting a terminal resize"""
|
"""Handle a keyboard event requesting a terminal resize"""
|
||||||
raise NotImplementedError('resizeterm')
|
raise NotImplementedError('resizeterm')
|
||||||
|
@ -403,6 +419,65 @@ class Notebook(Container, gtk.Notebook):
|
||||||
terms = parent.get_visible_terminals()
|
terms = parent.get_visible_terminals()
|
||||||
terms.keys()[-1].grab_focus()
|
terms.keys()[-1].grab_focus()
|
||||||
|
|
||||||
|
def page_num_descendant(self, widget):
|
||||||
|
"""Find the tabnum of the tab containing a widget at any level"""
|
||||||
|
tabnum = self.page_num(widget)
|
||||||
|
dbg("widget is direct child if not equal -1 - tabnum: %d" % tabnum)
|
||||||
|
while tabnum == -1 and widget.get_parent():
|
||||||
|
widget = widget.get_parent()
|
||||||
|
tabnum = self.page_num(widget)
|
||||||
|
dbg("found tabnum containing widget: %d" % tabnum)
|
||||||
|
return tabnum
|
||||||
|
|
||||||
|
def set_last_active_term(self, uuid):
|
||||||
|
"""Set the last active term for uuid"""
|
||||||
|
widget = self.terminator.find_terminal_by_uuid(uuid.urn)
|
||||||
|
if not widget:
|
||||||
|
err("Cannot find terminal with uuid: %s, so cannot make it active" % (uuid.urn))
|
||||||
|
return
|
||||||
|
tabnum = self.page_num_descendant(widget)
|
||||||
|
if tabnum == -1:
|
||||||
|
err("No tabnum found for terminal with uuid: %s" % (uuid.urn))
|
||||||
|
return
|
||||||
|
nth_page = self.get_nth_page(tabnum)
|
||||||
|
self.last_active_term[nth_page] = uuid
|
||||||
|
|
||||||
|
def clean_last_active_term(self):
|
||||||
|
"""Clean up old entries in last_active_term"""
|
||||||
|
if self.terminator.doing_layout == True:
|
||||||
|
return
|
||||||
|
last_active_term = {}
|
||||||
|
for tabnum in xrange(0, self.get_n_pages()):
|
||||||
|
nth_page = self.get_nth_page(tabnum)
|
||||||
|
if nth_page in self.last_active_term:
|
||||||
|
last_active_term[nth_page] = self.last_active_term[nth_page]
|
||||||
|
self.last_active_term = last_active_term
|
||||||
|
|
||||||
|
def deferred_on_tab_switch(self, notebook, page, page_num, data=None):
|
||||||
|
"""Prime a single idle tab switch signal, using the most recent set of params"""
|
||||||
|
tabs_last_active_term = self.last_active_term.get(self.get_nth_page(page_num), None)
|
||||||
|
data = {'tabs_last_active_term':tabs_last_active_term}
|
||||||
|
|
||||||
|
self.pending_on_tab_switch_args = (notebook, page, page_num, data)
|
||||||
|
if self.pending_on_tab_switch == True:
|
||||||
|
return
|
||||||
|
gobject.idle_add(self.do_deferred_on_tab_switch)
|
||||||
|
self.pending_on_tab_switch = True
|
||||||
|
|
||||||
|
def do_deferred_on_tab_switch(self):
|
||||||
|
"""Perform the latest tab switch signal, and resetting the pending flag"""
|
||||||
|
self.on_tab_switch(*self.pending_on_tab_switch_args)
|
||||||
|
self.pending_on_tab_switch = False
|
||||||
|
self.pending_on_tab_switch_args = None
|
||||||
|
|
||||||
|
def on_tab_switch(self, notebook, page, page_num, data=None):
|
||||||
|
"""Do the real work for a tab switch"""
|
||||||
|
tabs_last_active_term = data['tabs_last_active_term']
|
||||||
|
if tabs_last_active_term:
|
||||||
|
term = self.terminator.find_terminal_by_uuid(tabs_last_active_term.urn)
|
||||||
|
gobject.idle_add(term.ensure_visible_and_focussed)
|
||||||
|
return True
|
||||||
|
|
||||||
class TabLabel(gtk.HBox):
|
class TabLabel(gtk.HBox):
|
||||||
"""Class implementing a label widget for Notebook tabs"""
|
"""Class implementing a label widget for Notebook tabs"""
|
||||||
notebook = None
|
notebook = None
|
||||||
|
|
|
@ -1069,13 +1069,12 @@ class Terminal(gtk.VBox):
|
||||||
maker = Factory()
|
maker = Factory()
|
||||||
|
|
||||||
if maker.isinstance(topchild, 'Notebook'):
|
if maker.isinstance(topchild, 'Notebook'):
|
||||||
prevtmp = None
|
# Find which page number this term is on
|
||||||
tmp = self.get_parent()
|
tabnum = topchild.page_num_descendant(self)
|
||||||
while tmp != topchild:
|
# If terms page number is not the current one, switch to it
|
||||||
prevtmp = tmp
|
current_page = topchild.get_current_page()
|
||||||
tmp = tmp.get_parent()
|
if tabnum != current_page:
|
||||||
page = topchild.page_num(prevtmp)
|
topchild.set_current_page(tabnum)
|
||||||
topchild.set_current_page(page)
|
|
||||||
|
|
||||||
self.grab_focus()
|
self.grab_focus()
|
||||||
|
|
||||||
|
@ -1091,7 +1090,9 @@ class Terminal(gtk.VBox):
|
||||||
if not self.terminator.doing_layout:
|
if not self.terminator.doing_layout:
|
||||||
self.terminator.last_focused_term = self
|
self.terminator.last_focused_term = self
|
||||||
if self.get_toplevel().is_child_notebook():
|
if self.get_toplevel().is_child_notebook():
|
||||||
# TODO: Will need some code for the tabs active terms to work
|
notebook = self.get_toplevel().get_children()[0]
|
||||||
|
notebook.set_last_active_term(self.uuid)
|
||||||
|
notebook.clean_last_active_term()
|
||||||
self.get_toplevel().last_active_term = None
|
self.get_toplevel().last_active_term = None
|
||||||
else:
|
else:
|
||||||
self.get_toplevel().last_active_term = self.uuid
|
self.get_toplevel().last_active_term = self.uuid
|
||||||
|
|
|
@ -292,21 +292,54 @@ class Terminator(Borg):
|
||||||
def layout_done(self):
|
def layout_done(self):
|
||||||
"""Layout operations have finished, record that fact"""
|
"""Layout operations have finished, record that fact"""
|
||||||
self.doing_layout = False
|
self.doing_layout = False
|
||||||
|
maker = Factory()
|
||||||
|
|
||||||
window_last_active_term_mapping={}
|
window_last_active_term_mapping = {}
|
||||||
for window in self.windows:
|
for window in self.windows:
|
||||||
# TODO: Will need some code for the tabs active terms to work
|
if window.is_child_notebook():
|
||||||
window_last_active_term_mapping[window]=copy.deepcopy(window.last_active_term)
|
source = window.get_toplevel().get_children()[0]
|
||||||
|
else:
|
||||||
|
source = window
|
||||||
|
window_last_active_term_mapping[window] = copy.copy(source.last_active_term)
|
||||||
|
|
||||||
for terminal in self.terminals:
|
for terminal in self.terminals:
|
||||||
if not terminal.pid:
|
if not terminal.pid:
|
||||||
terminal.spawn_child()
|
terminal.spawn_child()
|
||||||
|
|
||||||
for window in self.windows:
|
for window in self.windows:
|
||||||
if window.last_active_term:
|
if window.is_child_notebook():
|
||||||
# TODO: Will need some code for the tabs active terms to work
|
# For windows with a notebook
|
||||||
term = self.find_terminal_by_uuid(window_last_active_term_mapping[window].urn)
|
notebook = window.get_toplevel().get_children()[0]
|
||||||
term.ensure_visible_and_focussed()
|
# Cycle through pages by number
|
||||||
|
for page in xrange(0, notebook.get_n_pages()):
|
||||||
|
# Try and get the entry in the previously saved mapping
|
||||||
|
mapping = window_last_active_term_mapping[window]
|
||||||
|
page_last_active_term = mapping.get(notebook.get_nth_page(page), None)
|
||||||
|
if page_last_active_term is None:
|
||||||
|
# Couldn't find entry, so we find the first child of type Terminal
|
||||||
|
children = notebook.get_nth_page(page).get_children()
|
||||||
|
for page_last_active_term in children:
|
||||||
|
if maker.isinstance(page_last_active_term, 'Terminal'):
|
||||||
|
page_last_active_term = page_last_active_term.uuid
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
err('Should never reach here!')
|
||||||
|
page_last_active_term = None
|
||||||
|
if page_last_active_term is None:
|
||||||
|
# Bail on this tab as we're having no luck here, continue with the next
|
||||||
|
continue
|
||||||
|
# Set the notebook entry, then ensure Terminal is visible and focussed
|
||||||
|
urn = page_last_active_term.urn
|
||||||
|
notebook.last_active_term[notebook.get_nth_page(page)] = page_last_active_term
|
||||||
|
if urn:
|
||||||
|
term = self.find_terminal_by_uuid(urn)
|
||||||
|
if term:
|
||||||
|
term.ensure_visible_and_focussed()
|
||||||
|
else:
|
||||||
|
# For windows without a notebook ensure Terminal is visible and focussed
|
||||||
|
if window_last_active_term_mapping[window]:
|
||||||
|
term = self.find_terminal_by_uuid(window_last_active_term_mapping[window].urn)
|
||||||
|
term.ensure_visible_and_focussed()
|
||||||
|
|
||||||
for window in self.windows:
|
for window in self.windows:
|
||||||
if window.uuid == self.last_active_window:
|
if window.uuid == self.last_active_window:
|
||||||
|
|
Loading…
Reference in New Issue