Initial cut of layout launcher. It 'aint pretty, but it works
This commit is contained in:
parent
c8b6268835
commit
e14cd19690
|
@ -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.
|
||||||
|
|
19
terminator
19
terminator
|
@ -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
|
||||||
|
|
|
@ -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': {
|
||||||
|
|
|
@ -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>
|
|
@ -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()
|
|
@ -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',
|
||||||
|
|
|
@ -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):
|
||||||
|
|
|
@ -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)
|
||||||
|
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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)
|
||||||
|
|
Loading…
Reference in New Issue