Merge feature-remember-focus branch, remembering focus and saving/loading to layouts
This commit is contained in:
commit
a638fb4980
|
@ -263,6 +263,7 @@ the %s will also close all terminals within it.') % (reqtype, reqtype))
|
|||
|
||||
if hasattr(self, 'isfullscreen'):
|
||||
layout['fullscreen'] = self.isfullscreen
|
||||
|
||||
if hasattr(self, 'ratio'):
|
||||
layout['ratio'] = self.ratio
|
||||
|
||||
|
@ -272,15 +273,26 @@ the %s will also close all terminals within it.') % (reqtype, reqtype))
|
|||
if hasattr(self, 'title'):
|
||||
layout['title'] = self.title.text
|
||||
|
||||
labels = []
|
||||
if mytype == 'Notebook':
|
||||
labels = []
|
||||
last_active_term = []
|
||||
for tabnum in xrange(0, self.get_n_pages()):
|
||||
page = self.get_nth_page(tabnum)
|
||||
label = self.get_tab_label(page)
|
||||
labels.append(label.get_custom_label())
|
||||
layout['active_page'] = self.get_current_page()
|
||||
if len(labels) > 0:
|
||||
last_active_term.append(self.last_active_term[self.get_nth_page(tabnum)])
|
||||
layout['labels'] = labels
|
||||
layout['last_active_term'] = last_active_term
|
||||
layout['active_page'] = self.get_current_page()
|
||||
else:
|
||||
if hasattr(self, 'last_active_term') and self.last_active_term is not None:
|
||||
layout['last_active_term'] = self.last_active_term
|
||||
|
||||
if mytype == 'Window':
|
||||
if self.uuid == self.terminator.last_active_window:
|
||||
layout['last_active_window'] = True
|
||||
else:
|
||||
layout['last_active_window'] = False
|
||||
|
||||
name = 'child%d' % count
|
||||
count = count + 1
|
||||
|
|
|
@ -12,11 +12,14 @@ from factory import Factory
|
|||
from container import Container
|
||||
from editablelabel import EditableLabel
|
||||
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 implementing a gtk.Notebook container"""
|
||||
window = None
|
||||
last_active_term = None
|
||||
pending_on_tab_switch = None
|
||||
pending_on_tab_switch_args = None
|
||||
|
||||
def __init__(self, window):
|
||||
"""Class initialiser"""
|
||||
|
@ -30,12 +33,16 @@ class Notebook(Container, gtk.Notebook):
|
|||
self.window = window
|
||||
gobject.type_register(Notebook)
|
||||
self.register_signals(Notebook)
|
||||
self.connect('switch-page', self.deferred_on_tab_switch)
|
||||
self.configure()
|
||||
|
||||
child = window.get_child()
|
||||
window.remove(child)
|
||||
window.add(self)
|
||||
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()
|
||||
|
||||
|
@ -63,6 +70,7 @@ class Notebook(Container, gtk.Notebook):
|
|||
style.xthickness = 0
|
||||
style.ythickness = 0
|
||||
self.modify_style(style)
|
||||
self.last_active_term = {}
|
||||
|
||||
def create_layout(self, layout):
|
||||
"""Apply layout configuration"""
|
||||
|
@ -117,10 +125,14 @@ class Notebook(Container, gtk.Notebook):
|
|||
label = self.get_tab_label(page)
|
||||
label.set_custom_label(labeltext)
|
||||
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
|
||||
|
||||
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:
|
||||
self.set_current_page(0)
|
||||
|
||||
|
@ -167,12 +179,13 @@ class Notebook(Container, gtk.Notebook):
|
|||
self.set_current_page(page_num)
|
||||
|
||||
self.show_all()
|
||||
terminal.grab_focus()
|
||||
|
||||
while gtk.events_pending():
|
||||
gtk.main_iteration_do(False)
|
||||
self.get_toplevel().set_pos_by_ratio = False
|
||||
|
||||
gobject.idle_add(terminal.ensure_visible_and_focussed)
|
||||
|
||||
def add(self, widget, metadata=None):
|
||||
"""Add a widget to the container"""
|
||||
dbg('adding a new tab')
|
||||
|
@ -268,15 +281,22 @@ class Notebook(Container, gtk.Notebook):
|
|||
|
||||
dbg('inserting page at position: %s' % tabpos)
|
||||
self.insert_page(widget, None, tabpos)
|
||||
self.set_tab_label(widget, label)
|
||||
self.set_tab_label_packing(widget, not self.config['scroll_tabbar'],
|
||||
child_widgets = [widget]
|
||||
child_widgets .extend(enumerate_descendants(widget))
|
||||
term_widget = None
|
||||
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_current_page(tabpos)
|
||||
self.show_all()
|
||||
if maker.isinstance(widget, 'Terminal'):
|
||||
if maker.isinstance(term_widget, 'Terminal'):
|
||||
widget.grab_focus()
|
||||
|
||||
def wrapcloseterm(self, widget):
|
||||
|
@ -311,6 +331,7 @@ class Notebook(Container, gtk.Notebook):
|
|||
|
||||
if maker.isinstance(child, 'Terminal'):
|
||||
dbg('Notebook::closetab: child is a single Terminal')
|
||||
del nb.last_active_term[child]
|
||||
child.close()
|
||||
# FIXME: We only do this del and return here to avoid removing the
|
||||
# page below, which child.close() implicitly does
|
||||
|
@ -318,9 +339,7 @@ class Notebook(Container, gtk.Notebook):
|
|||
return
|
||||
elif maker.isinstance(child, 'Container'):
|
||||
dbg('Notebook::closetab: child is a Container')
|
||||
dialog = self.construct_confirm_close(self.window, _('tab'))
|
||||
result = dialog.run()
|
||||
dialog.destroy()
|
||||
result = self.construct_confirm_close(self.window, _('tab'))
|
||||
|
||||
if result == gtk.RESPONSE_ACCEPT:
|
||||
containers = None
|
||||
|
@ -340,9 +359,6 @@ class Notebook(Container, gtk.Notebook):
|
|||
err('Notebook::closetab: child is unknown type %s' % child)
|
||||
return
|
||||
|
||||
nb.remove_page(tabnum)
|
||||
del(label)
|
||||
|
||||
def resizeterm(self, widget, keyname):
|
||||
"""Handle a keyboard event requesting a terminal resize"""
|
||||
raise NotImplementedError('resizeterm')
|
||||
|
@ -403,6 +419,65 @@ class Notebook(Container, gtk.Notebook):
|
|||
terms = parent.get_visible_terminals()
|
||||
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 implementing a label widget for Notebook tabs"""
|
||||
notebook = None
|
||||
|
|
|
@ -15,7 +15,7 @@ import pango
|
|||
import subprocess
|
||||
import urllib
|
||||
|
||||
from util import dbg, err, gerr, spawn_new_terminator
|
||||
from util import dbg, err, gerr, spawn_new_terminator, make_uuid
|
||||
import util
|
||||
from config import Config
|
||||
from cwd import get_default_cwd
|
||||
|
@ -1069,13 +1069,12 @@ class Terminal(gtk.VBox):
|
|||
maker = Factory()
|
||||
|
||||
if maker.isinstance(topchild, 'Notebook'):
|
||||
prevtmp = None
|
||||
tmp = self.get_parent()
|
||||
while tmp != topchild:
|
||||
prevtmp = tmp
|
||||
tmp = tmp.get_parent()
|
||||
page = topchild.page_num(prevtmp)
|
||||
topchild.set_current_page(page)
|
||||
# Find which page number this term is on
|
||||
tabnum = topchild.page_num_descendant(self)
|
||||
# If terms page number is not the current one, switch to it
|
||||
current_page = topchild.get_current_page()
|
||||
if tabnum != current_page:
|
||||
topchild.set_current_page(tabnum)
|
||||
|
||||
self.grab_focus()
|
||||
|
||||
|
@ -1088,7 +1087,15 @@ class Terminal(gtk.VBox):
|
|||
self.vte.set_colors(self.fgcolor_active, self.bgcolor,
|
||||
self.palette_active)
|
||||
self.set_cursor_color()
|
||||
if not self.terminator.doing_layout:
|
||||
self.terminator.last_focused_term = self
|
||||
if self.get_toplevel().is_child_notebook():
|
||||
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
|
||||
else:
|
||||
self.get_toplevel().last_active_term = self.uuid
|
||||
self.emit('focus-in')
|
||||
|
||||
def on_vte_focus_out(self, _widget, _event):
|
||||
|
@ -1490,6 +1497,7 @@ class Terminal(gtk.VBox):
|
|||
title = self.titlebar.get_custom_string()
|
||||
if title:
|
||||
layout['title'] = title
|
||||
layout['uuid'] = self.uuid
|
||||
name = 'terminal%d' % count
|
||||
count = count + 1
|
||||
global_layout[name] = layout
|
||||
|
@ -1511,6 +1519,8 @@ class Terminal(gtk.VBox):
|
|||
self.titlebar.set_custom_string(layout['title'])
|
||||
if layout.has_key('directory') and layout['directory'] != '':
|
||||
self.directory = layout['directory']
|
||||
if layout.has_key('uuid') and layout['uuid'] != '':
|
||||
self.uuid = make_uuid(layout['uuid'])
|
||||
|
||||
def scroll_by_page(self, pages):
|
||||
"""Scroll up or down in pages"""
|
||||
|
|
|
@ -34,6 +34,7 @@ class Terminator(Borg):
|
|||
debug_address = None
|
||||
|
||||
doing_layout = None
|
||||
last_active_window = None
|
||||
|
||||
groupsend = None
|
||||
groupsend_type = {'all':0, 'group':1, 'off':2}
|
||||
|
@ -291,11 +292,59 @@ class Terminator(Borg):
|
|||
def layout_done(self):
|
||||
"""Layout operations have finished, record that fact"""
|
||||
self.doing_layout = False
|
||||
maker = Factory()
|
||||
|
||||
window_last_active_term_mapping = {}
|
||||
for window in self.windows:
|
||||
if window.is_child_notebook():
|
||||
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:
|
||||
if not terminal.pid:
|
||||
terminal.spawn_child()
|
||||
|
||||
for window in self.windows:
|
||||
if window.is_child_notebook():
|
||||
# For windows with a notebook
|
||||
notebook = window.get_toplevel().get_children()[0]
|
||||
# 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:
|
||||
if window.uuid == self.last_active_window:
|
||||
window.show()
|
||||
|
||||
def reconfigure(self):
|
||||
"""Update configuration for the whole application"""
|
||||
|
||||
|
|
|
@ -277,8 +277,10 @@ def enumerate_descendants(parent):
|
|||
len(terminals), parent))
|
||||
return(containers, terminals)
|
||||
|
||||
def make_uuid():
|
||||
def make_uuid(str_uuid=None):
|
||||
"""Generate a UUID for an object"""
|
||||
if str_uuid:
|
||||
return uuid.UUID(str_uuid)
|
||||
return uuid.uuid4()
|
||||
|
||||
def inject_uuid(target):
|
||||
|
|
|
@ -5,12 +5,13 @@
|
|||
|
||||
import copy
|
||||
import time
|
||||
import uuid
|
||||
import pygtk
|
||||
pygtk.require('2.0')
|
||||
import gobject
|
||||
import gtk
|
||||
|
||||
from util import dbg, err
|
||||
from util import dbg, err, make_uuid
|
||||
import util
|
||||
from translation import _
|
||||
from version import APP_NAME
|
||||
|
@ -38,6 +39,7 @@ class Window(Container, gtk.Window):
|
|||
position = None
|
||||
ignore_startup_show = None
|
||||
set_pos_by_ratio = None
|
||||
last_active_term = None
|
||||
|
||||
zoom_data = None
|
||||
|
||||
|
@ -239,6 +241,17 @@ class Window(Container, gtk.Window):
|
|||
def on_focus_in(self, window, event):
|
||||
"""Focus has entered the window"""
|
||||
self.set_urgency_hint(False)
|
||||
term = None
|
||||
if self.is_child_notebook():
|
||||
# TODO: Will need some code for the tabs active terms to work
|
||||
pass
|
||||
else:
|
||||
if isinstance(self.last_active_term, uuid.UUID):
|
||||
term = self.terminator.find_terminal_by_uuid(self.last_active_term.urn)
|
||||
if term:
|
||||
gobject.idle_add(term.ensure_visible_and_focussed)
|
||||
if not self.terminator.doing_layout:
|
||||
self.terminator.last_active_window = self.uuid
|
||||
# FIXME: Cause the terminal titlebars to update here
|
||||
|
||||
def is_child_notebook(self):
|
||||
|
@ -865,6 +878,12 @@ class Window(Container, gtk.Window):
|
|||
|
||||
self.get_children()[0].create_layout(child)
|
||||
|
||||
if layout.has_key('last_active_term') and layout['last_active_term'] not in ['', None]:
|
||||
self.last_active_term = make_uuid(layout['last_active_term'])
|
||||
|
||||
if layout.has_key('last_active_window') and layout['last_active_window'] == 'True':
|
||||
self.terminator.last_active_window = self.uuid
|
||||
|
||||
class WindowTitle(object):
|
||||
"""Class to handle the setting of the window title"""
|
||||
|
||||
|
|
Loading…
Reference in New Issue