diff --git a/doc/terminator.1 b/doc/terminator.1
index c63edc16..71d86a20 100644
--- a/doc/terminator.1
+++ b/doc/terminator.1
@@ -45,7 +45,9 @@ based on the wishes of the child shell.
Specifies the preferred size and position of Terminator's window; see X(7).
.TP
.B \-e, \-\-command=COMMAND
-Runs the specified command instead of your default shell or profile specified command
+Runs the specified command instead of your default shell or profile specified command. Note: if
+Terminator is launched as x-terminal-emulator \-e behaves like \-x, and the longform becomes
+\-\-execute2=COMMAND
.TP
.B \-x, \-\-execute COMMAND [ARGS]
Runs \fBthe rest of the command line\fR instead of your default shell or profile specified command.
@@ -63,6 +65,9 @@ Set a custom name (WM_CLASS) property on the window
Start Terminator with a specific layout. The argument here is the name
of a saved layout.
.TP
+.B \-s, \-\-select-layout=LAYOUT
+Open the layout launcher window instead of the normal terminal.
+.TP
.B \-p, \-\-profile=PROFILE
Use a different profile as the default
.TP
@@ -94,10 +99,10 @@ used to spawn a new tab in the first Terminator window.
The following keybindings can be used to control Terminator:
.TP
.B Super+R
-\fBR\fotate terminals clockwise.
+\fBR\fRotate terminals clockwise.
.TP
.B Super+Shift+R
-\fBR\fotate terminals counter-clockwise.
+\fBR\fRotate terminals counter-clockwise.
.TP
.B Ctrl+Shift+O
Split terminals H\fBo\fRrizontally.
diff --git a/setup.py b/setup.py
index 4e5ee4c7..f8ea03fd 100755
--- a/setup.py
+++ b/setup.py
@@ -180,7 +180,7 @@ setup(name=APP_NAME.capitalize(),
],
packages=['terminatorlib', 'terminatorlib.configobj',
'terminatorlib.plugins'],
- package_data={'terminatorlib': ['preferences.glade']},
+ package_data={'terminatorlib': ['preferences.glade', 'layoutlauncher.glade']},
cmdclass={'build': BuildData, 'install_data': InstallData, 'uninstall': Uninstall},
distclass=TerminatorDist
)
diff --git a/terminator b/terminator
index 4302e11d..7175d264 100755
--- a/terminator
+++ b/terminator
@@ -47,6 +47,7 @@ from terminatorlib.terminator import Terminator
from terminatorlib.factory import Factory
from terminatorlib.version import APP_NAME, APP_VERSION
from terminatorlib.util import dbg, err
+from terminatorlib.layoutlauncher import LayoutLauncher
if __name__ == '__main__':
dbus_service = None
@@ -97,13 +98,17 @@ if __name__ == '__main__':
TERMINATOR.set_origcwd(ORIGCWD)
TERMINATOR.set_dbus_data(dbus_service)
TERMINATOR.reconfigure()
- try:
- dbg('Creating a terminal with layout: %s' % OPTIONS.layout)
- TERMINATOR.create_layout(OPTIONS.layout)
- except (KeyError,ValueError), ex:
- err('layout creation failed, creating a window ("%s")' % ex)
- TERMINATOR.new_window()
- TERMINATOR.layout_done()
+ if OPTIONS.select:
+ # launch gui, return selection
+ LAYOUTLAUNCHER=LayoutLauncher()
+ else:
+ try:
+ dbg('Creating a terminal with layout: %s' % OPTIONS.layout)
+ TERMINATOR.create_layout(OPTIONS.layout)
+ except (KeyError,ValueError), ex:
+ err('layout creation failed, creating a window ("%s")' % ex)
+ TERMINATOR.new_window()
+ TERMINATOR.layout_done()
if OPTIONS.debug > 2:
import terminatorlib.debugserver as debugserver
diff --git a/terminatorlib/config.py b/terminatorlib/config.py
index ec581bc4..f122287a 100755
--- a/terminatorlib/config.py
+++ b/terminatorlib/config.py
@@ -173,7 +173,8 @@ DEFAULTS = {
'broadcast_all' : '',
'insert_number' : '',
'insert_padded' : '',
- 'edit_window_title': ''
+ 'edit_window_title': '',
+ 'layout_launcher' : ''
},
'profiles': {
'default': {
@@ -619,6 +620,11 @@ class ConfigBase(Borg):
section_name)
self.loaded = True
+
+ def reload(self):
+ """Force a reload of the base config"""
+ self.loaded = False
+ self.load()
def save(self):
"""Save the config to a file"""
diff --git a/terminatorlib/container.py b/terminatorlib/container.py
index 59acdb3b..fba84fa4 100755
--- a/terminatorlib/container.py
+++ b/terminatorlib/container.py
@@ -256,6 +256,9 @@ the %s will also close all terminals within it.') % (reqtype, reqtype))
if hasattr(position, '__iter__'):
position = ':'.join([str(x) for x in position])
layout['position'] = position
+
+ if hasattr(self, 'ratio'):
+ layout['ratio'] = self.ratio
if hasattr(self, 'get_size'):
layout['size'] = self.get_size()
diff --git a/terminatorlib/layoutlauncher.glade b/terminatorlib/layoutlauncher.glade
new file mode 100644
index 00000000..477077fc
--- /dev/null
+++ b/terminatorlib/layoutlauncher.glade
@@ -0,0 +1,95 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/terminatorlib/layoutlauncher.py b/terminatorlib/layoutlauncher.py
new file mode 100755
index 00000000..41a0c416
--- /dev/null
+++ b/terminatorlib/layoutlauncher.py
@@ -0,0 +1,97 @@
+#!/usr/bin/python
+# Terminator by Chris Jones
+# GPL v2 only
+"""layoutlauncher.py - class for the Layout Launcher window"""
+
+import os
+import gtk
+
+from util import dbg, err, spawn_new_terminator
+import config
+from translation import _
+from terminator import Terminator
+from plugin import PluginRegistry
+
+class LayoutLauncher:
+ """Class implementing the various parts of the preferences editor"""
+ terminator = None
+ config = None
+ registry = None
+ plugins = None
+ keybindings = None
+ window = None
+ builder = None
+ layouttreeview = None
+ layouttreestore = None
+
+ def __init__ (self):
+ self.terminator = Terminator()
+ self.terminator.register_launcher_window(self)
+
+ self.config = config.Config()
+ self.builder = gtk.Builder()
+ try:
+ # Figure out where our library is on-disk so we can open our UI
+ (head, _tail) = os.path.split(config.__file__)
+ librarypath = os.path.join(head, 'layoutlauncher.glade')
+ gladefile = open(librarypath, 'r')
+ gladedata = gladefile.read()
+ except Exception, ex:
+ print "Failed to find layoutlauncher.glade"
+ print ex
+ return
+
+ self.builder.add_from_string(gladedata)
+ self.window = self.builder.get_object('layoutlauncherwin')
+ self.builder.connect_signals(self)
+ self.window.connect('destroy', self.on_destroy_event)
+ self.window.show_all()
+ self.layouttreeview = self.builder.get_object('layoutlist')
+ self.layouttreestore = self.builder.get_object('layoutstore')
+ self.update_layouts()
+
+ def on_destroy_event(self, widget, data=None):
+ """Handle window destruction"""
+ dbg('destroying self')
+ self.terminator.deregister_launcher_window(self)
+ self.window.destroy()
+ del(self.window)
+
+ def update_layouts(self):
+ """Update the contents of the layout"""
+ self.layouttreestore.clear()
+ layouts = self.config.list_layouts()
+ for layout in sorted(layouts, cmp=lambda x,y: cmp(x.lower(), y.lower())):
+ if layout != "default":
+ self.layouttreestore.append([layout])
+ else:
+ self.layouttreestore.prepend([layout])
+
+ def on_launchbutton_clicked(self, widget):
+ """Handle button click"""
+ self.launch_layout()
+
+ def on_row_activated(self, widget, path, view_column):
+ """Handle item double-click and return"""
+ self.launch_layout()
+
+ def launch_layout(self):
+ """Launch the selected layout as new instance"""
+ dbg('We have takeoff!')
+ selection=self.layouttreeview.get_selection()
+ (listmodel, rowiter) = selection.get_selected()
+ if not rowiter:
+ # Something is wrong, just jump to the first item in the list
+ selection.select_iter(self.layouttreestore.get_iter_first())
+ (listmodel, rowiter) = selection.get_selected()
+ layout = listmodel.get_value(rowiter, 0)
+ dbg('Clicked for %s' % layout)
+ spawn_new_terminator(self.terminator.origcwd, ['-u', '-l', layout])
+
+if __name__ == '__main__':
+ import util
+ util.DEBUG = True
+ import terminal
+ LAYOUTLAUNCHER = LayoutLauncher()
+
+ gtk.main()
diff --git a/terminatorlib/optionparse.py b/terminatorlib/optionparse.py
index e395f590..1c36ad21 100755
--- a/terminatorlib/optionparse.py
+++ b/terminatorlib/optionparse.py
@@ -86,7 +86,9 @@ icon for the window (by file or name)'))
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'))
+ help=_('Launch with the given layout'))
+ parser.add_option('-s', '--select-layout', action='store_true',
+ dest='select', help=_('Select a layout from a list'))
parser.add_option('-p', '--profile', dest='profile',
help=_('Use a different profile as the default'))
parser.add_option('-u', '--no-dbus', action='store_true', dest='nodbus',
diff --git a/terminatorlib/paned.py b/terminatorlib/paned.py
index 3a3eafab..119b437d 100755
--- a/terminatorlib/paned.py
+++ b/terminatorlib/paned.py
@@ -350,9 +350,10 @@ class Paned(Container):
self.get_child1().create_layout(children[keys[0]])
self.get_child2().create_layout(children[keys[1]])
- # Store the position for later
- if layout['position']:
- self.position = int(layout['position'])
+ # Set the position with ratio. For some reason more reliable than by pos.
+ if layout.has_key('ratio'):
+ self.ratio = float(layout['ratio'])
+ self.set_position_by_ratio()
def grab_focus(self):
"""We don't want focus, we want a Terminal to have it"""
diff --git a/terminatorlib/prefseditor.py b/terminatorlib/prefseditor.py
index 46c4aca5..bbc063b7 100755
--- a/terminatorlib/prefseditor.py
+++ b/terminatorlib/prefseditor.py
@@ -143,11 +143,13 @@ class PrefsEditor:
'broadcast_all' : 'Broadcast key events to all',
'insert_number' : 'Insert terminal number',
'insert_padded' : 'Insert zero padded terminal number',
- 'edit_window_title': 'Edit window title'
+ 'edit_window_title': 'Edit window title',
+ 'layout_launcher' : 'Open layout launcher window'
}
def __init__ (self, term):
self.config = config.Config()
+ self.config.base.reload()
self.term = term
self.builder = gtk.Builder()
self.keybindings = Keybindings()
diff --git a/terminatorlib/terminal.py b/terminatorlib/terminal.py
index e540f85c..1fe71957 100755
--- a/terminatorlib/terminal.py
+++ b/terminatorlib/terminal.py
@@ -15,7 +15,7 @@ import pango
import subprocess
import urllib
-from util import dbg, err, gerr
+from util import dbg, err, gerr, spawn_new_terminator
import util
from config import Config
from cwd import get_default_cwd
@@ -27,6 +27,7 @@ from searchbar import Searchbar
from translation import _
from signalman import Signalman
import plugin
+from terminatorlib.layoutlauncher import LayoutLauncher
try:
import vte
@@ -1680,18 +1681,7 @@ class Terminal(gtk.VBox):
self.terminator.new_window(self.terminator.pid_cwd(self.pid))
def key_new_terminator(self):
- cmd = sys.argv[0]
-
- if not os.path.isabs(cmd):
- # Command is not an absolute path. Figure out where we are
- cmd = os.path.join (self.origcwd, sys.argv[0])
- if not os.path.isfile(cmd):
- # we weren't started as ./terminator in a path. Give up
- err('Terminal::key_new_window: Unable to locate Terminator')
- return False
-
- dbg("Terminal::key_new_window: Spawning: %s" % cmd)
- subprocess.Popen([cmd, '-u'])
+ spawn_new_terminator(self.origcwd, ['-u'])
def key_broadcast_off(self):
self.set_groupsend(None, self.terminator.groupsend_type['off'])
@@ -1742,6 +1732,9 @@ class Terminal(gtk.VBox):
dialog.destroy()
return
+ def key_layout_launcher(self):
+ LAYOUTLAUNCHER=LayoutLauncher()
+
def key_page_up(self):
self.scroll_by_page(-1)
diff --git a/terminatorlib/terminator.py b/terminatorlib/terminator.py
index 464d4c3c..831bd094 100755
--- a/terminatorlib/terminator.py
+++ b/terminatorlib/terminator.py
@@ -19,6 +19,7 @@ class Terminator(Borg):
"""master object for the application"""
windows = None
+ launcher_windows = None
windowtitle = None
terminals = None
groups = None
@@ -48,6 +49,8 @@ class Terminator(Borg):
if not self.windows:
self.windows = []
+ if not self.launcher_windows:
+ self.launcher_windows = []
if not self.terminals:
self.terminals = []
if not self.groups:
@@ -129,6 +132,27 @@ class Terminator(Borg):
dbg('no windows remain, quitting')
gtk.main_quit()
+ def register_launcher_window(self, window):
+ """Register a new launcher window widget"""
+ if window not in self.launcher_windows:
+ dbg('Terminator::register_launcher_window: registering %s:%s' % (id(window),
+ type(window)))
+ self.launcher_windows.append(window)
+
+ def deregister_launcher_window(self, window):
+ """de-register a launcher window widget"""
+ dbg('Terminator::deregister_launcher_window: de-registering %s:%s' %
+ (id(window), type(window)))
+ if window in self.launcher_windows:
+ self.launcher_windows.remove(window)
+ else:
+ err('%s is not in registered window list' % window)
+
+ if len(self.launcher_windows) == 0 and len(self.windows) == 0:
+ # We have no windows left, we should exit
+ dbg('no windows remain, quitting')
+ gtk.main_quit()
+
def register_terminal(self, terminal):
"""Register a new terminal widget"""
if terminal not in self.terminals:
@@ -238,7 +262,6 @@ class Terminator(Borg):
raise(ValueError)
dbg('Creating a window')
window, terminal = self.new_window()
- window.create_layout(layout[windef])
if layout[windef].has_key('position'):
parts = layout[windef]['position'].split(':')
if len(parts) == 2:
@@ -251,6 +274,7 @@ class Terminator(Borg):
window.resize(winx, winy)
if layout[windef].has_key('title'):
window.title.force_title(layout[windef]['title'])
+ window.create_layout(layout[windef])
def layout_done(self):
"""Layout operations have finished, record that fact"""
diff --git a/terminatorlib/util.py b/terminatorlib/util.py
index b8ad5aba..c9143df2 100755
--- a/terminatorlib/util.py
+++ b/terminatorlib/util.py
@@ -29,6 +29,7 @@ import os
import pwd
import inspect
import uuid
+import subprocess
# set this to true to enable debugging output
DEBUG = False
@@ -289,3 +290,17 @@ def inject_uuid(target):
else:
dbg("Object already has a UUID: %s" % target)
+def spawn_new_terminator(cwd, args):
+ """Start a new terminator instance with the given arguments"""
+ cmd = sys.argv[0]
+
+ if not os.path.isabs(cmd):
+ # Command is not an absolute path. Figure out where we are
+ cmd = os.path.join (cwd, sys.argv[0])
+ if not os.path.isfile(cmd):
+ # we weren't started as ./terminator in a path. Give up
+ err('Unable to locate Terminator')
+ return False
+
+ dbg("Spawning: %s" % cmd)
+ subprocess.Popen([cmd]+args)