Initial cut of layout launcher. It 'aint pretty, but it works

This commit is contained in:
Stephen Boddy 2013-08-28 23:09:17 +02:00
parent c8b6268835
commit e14cd19690
10 changed files with 269 additions and 26 deletions

View File

@ -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). Specifies the preferred size and position of Terminator's window; see X(7).
.TP .TP
.B \-e, \-\-command=COMMAND .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 .TP
.B \-x, \-\-execute COMMAND [ARGS] .B \-x, \-\-execute COMMAND [ARGS]
Runs \fBthe rest of the command line\fR instead of your default shell or profile specified command. 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 Start Terminator with a specific layout. The argument here is the name
of a saved layout. of a saved layout.
.TP .TP
.B \-s, \-\-select-layout=LAYOUT
Open the layout launcher window instead of the normal terminal.
.TP
.B \-p, \-\-profile=PROFILE .B \-p, \-\-profile=PROFILE
Use a different profile as the default Use a different profile as the default
.TP .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: The following keybindings can be used to control Terminator:
.TP .TP
.B Super+R .B Super+R
\fBR\fotate terminals clockwise. \fBR\fRotate terminals clockwise.
.TP .TP
.B Super+Shift+R .B Super+Shift+R
\fBR\fotate terminals counter-clockwise. \fBR\fRotate terminals counter-clockwise.
.TP .TP
.B Ctrl+Shift+O .B Ctrl+Shift+O
Split terminals H\fBo\fRrizontally. Split terminals H\fBo\fRrizontally.

View File

@ -47,6 +47,7 @@ from terminatorlib.terminator import Terminator
from terminatorlib.factory import Factory from terminatorlib.factory import Factory
from terminatorlib.version import APP_NAME, APP_VERSION from terminatorlib.version import APP_NAME, APP_VERSION
from terminatorlib.util import dbg, err from terminatorlib.util import dbg, err
from terminatorlib.layoutlauncher import LayoutLauncher
if __name__ == '__main__': if __name__ == '__main__':
dbus_service = None dbus_service = None
@ -97,13 +98,17 @@ if __name__ == '__main__':
TERMINATOR.set_origcwd(ORIGCWD) TERMINATOR.set_origcwd(ORIGCWD)
TERMINATOR.set_dbus_data(dbus_service) TERMINATOR.set_dbus_data(dbus_service)
TERMINATOR.reconfigure() TERMINATOR.reconfigure()
try: if OPTIONS.select:
dbg('Creating a terminal with layout: %s' % OPTIONS.layout) # launch gui, return selection
TERMINATOR.create_layout(OPTIONS.layout) LAYOUTLAUNCHER=LayoutLauncher()
except (KeyError,ValueError), ex: else:
err('layout creation failed, creating a window ("%s")' % ex) try:
TERMINATOR.new_window() dbg('Creating a terminal with layout: %s' % OPTIONS.layout)
TERMINATOR.layout_done() 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: if OPTIONS.debug > 2:
import terminatorlib.debugserver as debugserver import terminatorlib.debugserver as debugserver

View File

@ -173,7 +173,8 @@ DEFAULTS = {
'broadcast_all' : '', 'broadcast_all' : '',
'insert_number' : '', 'insert_number' : '',
'insert_padded' : '', 'insert_padded' : '',
'edit_window_title': '' 'edit_window_title': '',
'layout_launcher' : ''
}, },
'profiles': { 'profiles': {
'default': { 'default': {

View File

@ -0,0 +1,94 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<requires lib="gtk+" version="2.18"/>
<!-- interface-naming-policy project-wide -->
<object class="GtkWindow" id="layoutlauncherwin">
<property name="can_focus">False</property>
<property name="title" translatable="yes">Terminator Layout Launcher</property>
<signal name="destroy-event" handler="on_destroy_event" swapped="no"/>
<child>
<object class="GtkVBox" id="vbox1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="border_width">7</property>
<property name="spacing">7</property>
<child>
<object class="GtkFrame" id="frame1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label_xalign">0</property>
<property name="label_yalign">0</property>
<property name="shadow_type">in</property>
<child>
<object class="GtkTreeView" id="layoutlist">
<property name="width_request">150</property>
<property name="height_request">200</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="model">layoutstore</property>
<property name="headers_clickable">False</property>
<property name="search_column">0</property>
<child>
<object class="GtkTreeViewColumn" id="treeviewcolumn1">
<property name="title" translatable="yes">Layout</property>
<child>
<object class="GtkCellRendererText" id="cellrenderertext1"/>
<attributes>
<attribute name="text">0</attribute>
</attributes>
</child>
</object>
</child>
</object>
</child>
<child type="label_item">
<placeholder/>
</child>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkHBox" id="hbox1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<placeholder/>
</child>
<child>
<object class="GtkButton" id="launchbutton">
<property name="label" translatable="yes">Launch</property>
<property name="width_request">100</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="use_action_appearance">False</property>
<signal name="clicked" handler="on_launchbutton_clicked" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="pack_type">end</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
</child>
</object>
<object class="GtkListStore" id="layoutstore">
<columns>
<!-- column-name layoutname -->
<column type="gchararray"/>
</columns>
</object>
</interface>

103
terminatorlib/layoutlauncher.py Executable file
View File

@ -0,0 +1,103 @@
#!/usr/bin/python
"""Layout Launcher for Terminator.
Load a UIBuilder config file, display it, populate it with our current layouts,
then allow launching it as a new instance
"""
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): #, term):
self.terminator = Terminator()
self.terminator.register_launcher_window(self)
self.config = config.Config()
#self.term = term
self.builder = gtk.Builder()
#self.keybindings = Keybindings()
try:
# Figure out where our library is on-disk so we can open our
(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.layouteditor = LayoutEditor(self.builder)
self.builder.connect_signals(self)
self.window.connect('destroy', self.on_destroy_event)
#self.layouteditor.prepare()
self.window.show_all()
self.layouttreeview = self.builder.get_object('layoutlist')
self.layouttreestore = self.builder.get_object('layoutstore')
self.update_layouts()
try:
#self.config.inhibit_save()
#self.set_values()
pass
except Exception, e:
err('Unable to set values: %s' % e)
#self.config.uninhibit_save()
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):
"""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()

View File

@ -86,7 +86,9 @@ icon for the window (by file or name)'))
parser.add_option('-r', '--role', dest='role', parser.add_option('-r', '--role', dest='role',
help=_('Set a custom WM_WINDOW_ROLE property on the window')) help=_('Set a custom WM_WINDOW_ROLE property on the window'))
parser.add_option('-l', '--layout', dest='layout', 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', parser.add_option('-p', '--profile', dest='profile',
help=_('Use a different profile as the default')) help=_('Use a different profile as the default'))
parser.add_option('-u', '--no-dbus', action='store_true', dest='nodbus', parser.add_option('-u', '--no-dbus', action='store_true', dest='nodbus',

View File

@ -143,7 +143,8 @@ class PrefsEditor:
'broadcast_all' : 'Broadcast key events to all', 'broadcast_all' : 'Broadcast key events to all',
'insert_number' : 'Insert terminal number', 'insert_number' : 'Insert terminal number',
'insert_padded' : 'Insert zero padded 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): def __init__ (self, term):

View File

@ -15,7 +15,7 @@ import pango
import subprocess import subprocess
import urllib import urllib
from util import dbg, err, gerr from util import dbg, err, gerr, spawn_new_terminator
import util import util
from config import Config from config import Config
from cwd import get_default_cwd from cwd import get_default_cwd
@ -27,6 +27,7 @@ from searchbar import Searchbar
from translation import _ from translation import _
from signalman import Signalman from signalman import Signalman
import plugin import plugin
from terminatorlib.layoutlauncher import LayoutLauncher
try: try:
import vte import vte
@ -1680,18 +1681,7 @@ class Terminal(gtk.VBox):
self.terminator.new_window(self.terminator.pid_cwd(self.pid)) self.terminator.new_window(self.terminator.pid_cwd(self.pid))
def key_new_terminator(self): def key_new_terminator(self):
cmd = sys.argv[0] spawn_new_terminator(self.origcwd, ['-u'])
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'])
def key_broadcast_off(self): def key_broadcast_off(self):
self.set_groupsend(None, self.terminator.groupsend_type['off']) self.set_groupsend(None, self.terminator.groupsend_type['off'])
@ -1742,6 +1732,9 @@ class Terminal(gtk.VBox):
dialog.destroy() dialog.destroy()
return return
def key_layout_launcher(self):
LAYOUTLAUNCHER=LayoutLauncher()
def key_page_up(self): def key_page_up(self):
self.scroll_by_page(-1) self.scroll_by_page(-1)

View File

@ -19,6 +19,7 @@ class Terminator(Borg):
"""master object for the application""" """master object for the application"""
windows = None windows = None
launcher_windows = None
windowtitle = None windowtitle = None
terminals = None terminals = None
groups = None groups = None
@ -48,6 +49,8 @@ class Terminator(Borg):
if not self.windows: if not self.windows:
self.windows = [] self.windows = []
if not self.launcher_windows:
self.launcher_windows = []
if not self.terminals: if not self.terminals:
self.terminals = [] self.terminals = []
if not self.groups: if not self.groups:
@ -129,6 +132,27 @@ class Terminator(Borg):
dbg('no windows remain, quitting') dbg('no windows remain, quitting')
gtk.main_quit() 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): def register_terminal(self, terminal):
"""Register a new terminal widget""" """Register a new terminal widget"""
if terminal not in self.terminals: if terminal not in self.terminals:

View File

@ -29,6 +29,7 @@ import os
import pwd import pwd
import inspect import inspect
import uuid import uuid
import subprocess
# set this to true to enable debugging output # set this to true to enable debugging output
DEBUG = False DEBUG = False
@ -289,3 +290,17 @@ def inject_uuid(target):
else: else:
dbg("Object already has a UUID: %s" % target) 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)