예제 #1
0
    def prepare_attributes(self):
        """Initialise anything that isn't already"""

        if not self.windows:
            self.windows = []
        if not self.launcher_windows:
            self.launcher_windows = []
        if not self.terminals:
            self.terminals = []
        if not self.groups:
            self.groups = []
        if not self.config:
            self.config = Config()
        if self.groupsend == None:
            self.groupsend = self.groupsend_type[
                self.config['broadcast_default']]
        if not self.keybindings:
            self.keybindings = Keybindings()
            self.keybindings.configure(self.config['keybindings'])
        if not self.style_providers:
            self.style_providers = []
        if not self.doing_layout:
            self.doing_layout = False
        if not self.pid_cwd:
            self.pid_cwd = get_pid_cwd()
        if self.gnome_client is None:
            self.attempt_gnome_client()
        self.connect_signals()
예제 #2
0
 def __init__( self):
   config = Config()
   sections = config.plugin_get_config(self.__class__.__name__)
   if not isinstance(sections, dict):
       return
   noord_cmds = []
   for part in sections:
     s = sections[part]
     if not ("name" in s and "command" in s):
       print("CustomCommandsMenu: Ignoring section %s" % s)
       continue
     name = s["name"]
     command = s["command"]
     enabled = s["enabled"] and s["enabled"] or False
     if "position" in s:
       self.cmd_list[int(s["position"])] = {'enabled' : enabled,
                                            'name' : name,
                                            'command' : command
                                           }
     else:
       noord_cmds.append(
                           {'enabled' : enabled,
                             'name' : name,
                             'command' : command
                           }
                         )
     for cmd in noord_cmds:
         self.cmd_list[len(self.cmd_list)] = cmd
예제 #3
0
 def __init__(self):
     config = Config()
     sections = config.plugin_get_config(self.__class__.__name__)
     if not isinstance(sections, dict):
         return
     noord_cmds = []
     for part in sections:
         s = sections[part]
         if not (s.has_key("name") and s.has_key("command")):
             print "CustomCommandsMenu: Ignoring section %s" % s
             continue
         name = s["name"]
         command = s["command"]
         enabled = s["enabled"] and s["enabled"] or False
         if s.has_key("position"):
             self.cmd_list[int(s["position"])] = {
                 'enabled': enabled,
                 'name': name,
                 'command': command
             }
         else:
             noord_cmds.append({
                 'enabled': enabled,
                 'name': name,
                 'command': command
             })
         for cmd in noord_cmds:
             self.cmd_list[len(self.cmd_list)] = cmd
예제 #4
0
    def __init__(self):
        config = Config()
        sections = config.plugin_get_config(self.__class__.__name__)
        if not isinstance(sections, dict):
            return
        noord_cmds = []
        for part in sections:
            s = sections[part]
            if not ("regexp" in s and "command" in s):
                dbg("Ignoring section %s" % s)
                continue
            regexp = s["regexp"]
            command = s["command"]
            enabled = s["enabled"] and s["enabled"] or False
            if "position" in s:
                self.cmd_list[int(s["position"])] = {
                    'enabled': enabled,
                    'regexp': regexp,
                    'command': command
                }
            else:
                noord_cmds.append({
                    'enabled': enabled,
                    'regexp': regexp,
                    'command': command
                })
            for cmd in noord_cmds:
                self.cmd_list[len(self.cmd_list)] = cmd

            self._load_configured_handlers()
예제 #5
0
    def _load_configured_handlers(self):
        """Forge an URLhandler plugin and hide it in the available ones."""
        me = sys.modules[__name__]  # Current module.
        config = Config()

        for key, handler in [(key, self.cmd_list[key])
                             for key in sorted(self.cmd_list.keys())]:
            # Forge a hidden/managed plugin
            # (names starting with an underscore will not be displayed in the preference/plugins window).
            rcom_name = "_RunCmdOnMatch_{}".format(
                key)  # key is just the index
            # Make a handler class.
            RCOM = MetaRCOM(rcom_name, handler["regexp"], handler["command"])
            # Instanciate the class.
            setattr(me, rcom_name, RCOM)

            if rcom_name not in AVAILABLE:
                AVAILABLE.append(rcom_name)
                dbg("add {} to the list of URL handlers: '{}' -> '{}'".format(
                    rcom_name, RCOM.match, RCOM.cmd))

            if handler['enabled'] and rcom_name not in config[
                    "enabled_plugins"]:
                config["enabled_plugins"].append(rcom_name)

        config.save()
예제 #6
0
 def __init__(self):
     config = Config()
     sections = config.plugin_get_config(self.__class__.__name__)
     if not isinstance(sections, dict):
         return
     noord_cmds = []
     for part in sections:
         s = sections[part]
         if not ('name' in s and 'command' in s):
             print(f'CustomCommandsMenu: Ignoring section {s}')
             continue
         name = s['name']
         command = s['command']
         enabled = s['enabled'] and s['enabled'] or False
         if 'position' in s:
             self.cmd_list[int(s['position'])] = {
                 'enabled': enabled,
                 'name': name,
                 'command': command
             }
         else:
             noord_cmds.append({
                 'enabled': enabled,
                 'name': name,
                 'command': command
             })
         for cmd in noord_cmds:
             self.cmd_list[len(self.cmd_list)] = cmd
예제 #7
0
 def __init__(self):
     self.config = Config().plugin_get_config(self.__class__.__name__)
     self.triggers = {}
     self.watches = {}
     self.load_triggers()
     self.update_watches()
     self.dialog_in_process = set()
     keepassDb = ''
     if 'keepassDb' in self.config:
         keepassDb = self.config['keepassDb']
     self.triggersCommand = TriggersCommand(keepassDb)
예제 #8
0
 def __init__(self):
     config = Config()
     sections = config.plugin_get_config(self.__class__.__name__)
     if not isinstance(sections, dict):
         return
     for part in sections:
         s = sections[part]
         if not (s.has_key("name") and s.has_key("command")):
             print "SSHMenu: Ignoring section %s" % s
             continue
         name = s["name"]
         command = s["command"]
         self.cmd_list.append({'name': name, 'command': command})
 def __init__(self):
     super(TerminalExporter, self).__init__()
     self.config = Config()
     self.plugin_config = parse_plugin_config(self.config)
     self.logging_terminals = {}
     self.scrollback_lines = self.config['scrollback_lines']
     dbg('using config: %s' % self.plugin_config)
예제 #10
0
    def __init__(self):
        self.config = Config().plugin_get_config(self.__class__.__name__)
        self.watches = {}

        self.images = self.load_images()
        dbg(self.images)

        global_config = Terminator().config
        # Create ssh profiles
        self.ssh_profiles = {}
        for f in glob.glob(self.images):
            dbg(f)
            name = os.path.splitext(os.path.basename(f))[0]
            self.ssh_profiles[name] = f
            global_config.add_profile(name)
            profile = global_config.base.profiles[name]
            profile["background_darkness"] = 0.88
            profile["background_image"] = f
            profile["background_type"] = "image"

        dbg(repr(self.ssh_profiles))

        for v in global_config.list_profiles():
            dbg(repr(v))

        self.failback_profile = self.get_failback()
        self.last_profile = self.failback_profile
        self.load_patterns()
        self.update_watches()
예제 #11
0
    def __init__(self):
        plugin.MenuItem.__init__(self)
        self.config = Config()
        colorize_config = self.config.plugin_get_config(
            self.__class__.__name__)
        if not colorize_config:
            colorize_config = self.presets
        self.color_set = []
        counter = 0
        if colorize_config:
            while colorize_config.get('color' + str(counter)):
                self.color_set.append(
                    colorize_config.get('color' + str(counter)))
                counter += 1

        dbg(self.color_set)
예제 #12
0
 def __init__(self):
     plugin.MenuItem.__init__(self)
     self.config = Config()
     self.pluginConfig = parsePluginConfig(self.config)
     self.loggingTerminals = {}
     self.scrollbackLines = self.config['scrollback_lines']
     dbg("using config: %s" % self.pluginConfig)
예제 #13
0
    def __init__(self):
        """Class initialiser"""
        GObject.GObject.__init__(self)

        self.config = Config()

        self.get_style_context().add_class("terminator-terminal-searchbar")

        # Search text
        self.entry = Gtk.Entry()
        self.entry.set_activates_default(True)
        self.entry.show()
        self.entry.connect('activate', self.do_search)
        self.entry.connect('key-press-event', self.search_keypress)

        # Label
        label = Gtk.Label(label=_('Search:'))
        label.show()

        # Close Button
        close = Gtk.Button()
        close.set_relief(Gtk.ReliefStyle.NONE)
        close.set_focus_on_click(False)
        icon = Gtk.Image()
        icon.set_from_stock(Gtk.STOCK_CLOSE, Gtk.IconSize.MENU)
        close.add(icon)
        close.set_name('terminator-search-close-button')
        if hasattr(close, 'set_tooltip_text'):
            close.set_tooltip_text(_('Close Search bar'))
        close.connect('clicked', self.end_search)
        close.show_all()

        # Next Button
        self.next = Gtk.Button(label=_('Next'))
        self.next.show()
        self.next.set_sensitive(False)
        self.next.connect('clicked', self.next_search)

        # Previous Button
        self.prev = Gtk.Button(label=_('Prev'))
        self.prev.show()
        self.prev.set_sensitive(False)
        self.prev.connect('clicked', self.prev_search)

        # Wrap checkbox
        self.wrap = Gtk.CheckButton(label=_('Wrap'))
        self.wrap.show()
        self.wrap.set_sensitive(True)
        self.wrap.connect('toggled', self.wrap_toggled)

        self.pack_start(label, False, True, 0)
        self.pack_start(self.entry, True, True, 0)
        self.pack_start(self.prev, False, False, 0)
        self.pack_start(self.next, False, False, 0)
        self.pack_start(self.wrap, False, False, 0)
        self.pack_end(close, False, False, 0)

        self.hide()
        self.set_no_show_all(True)
예제 #14
0
 def callback(self, menuitems, menu, terminal):
     self.config = Config()
     self.terminal = terminal
     self.profiles = self.terminal.config.list_profiles()
     target = random.randrange(0, len(self.profiles))
     currentProfile = self.profiles[target]
     widget = self.terminal.get_vte()
     self.terminal.force_set_profile(widget, currentProfile)
예제 #15
0
    def _save_config(self):
      config = Config()
      i = 0
      length = len(self.cmd_list)
      while i < length:
        enabled = self.cmd_list[i]['enabled']
        name = self.cmd_list[i]['name']
        command = self.cmd_list[i]['command']
       
        item = {}
        item['enabled'] = enabled
        item['name'] = name
        item['command'] = command

        config.plugin_set(self.__class__.__name__, name, item)
        config.save()
        i = i + 1
예제 #16
0
 def __init__( self):
   config = Config()
   sections = config.plugin_get_config(self.__class__.__name__)
   if not isinstance(sections, dict):
       return
   for part in sections:
     s = sections[part]
     if not (s.has_key("name") and s.has_key("command")):
       print "CustomCommandsMenu: Ignoring section %s" % s
       continue
     name = s["name"]
     command = s["command"]
     enabled = s["enabled"] and s["enabled"] or False
     self.cmd_list.append(
                           {'enabled' : enabled,
                             'name' : name,
                             'command' : command
                           }
                         )
예제 #17
0
 def __init__(self):
     self.config = Config().plugin_get_config(self.__class__.__name__)
     self.watches = {}
     self.prompt_minlen = int(self.get_prompt_minlen())
     self.line_minlen = int(self.get_line_minlen())
     self.failback_profile = self.get_failback()
     self.last_profile = self.failback_profile
     self.load_patterns()
     self.load_profile_mappings()
     self.update_watches()
예제 #18
0
    def __init__(self):
        self.config = Config()

        if self.config.plugin_get_config(self.plugin_name) is None:
            for key, value in CONFIG_DEFAULTS.iteritems():
                self.config.plugin_set(self.plugin_name, key, value)
            self.config.save()

        self.match = self.config.plugin_get(self.plugin_name, "match")
        self.jira_url = self.config.plugin_get(self.plugin_name, "jira_url")
    def __init__(self):
        self.config = Config()
        if not isinstance(
            self.config.plugin_get_config(
                self.__class__.__name__), dict):
            self.config.plugin_set_config(self.__class__.__name__, {})
            self.config.save()

        self._authorization = dict(Authorization='Bearer ' + TOKEN)
        self._base_api_url = 'https://api.online.net/api/v1'
        self._servers_infos_file_name = '/tmp/online_servers_infos'
예제 #20
0
    def __init__( self):
      self.cmd_list = []
      self.cur_input = ''
      config = Config()
      sections = config.plugin_get_config(self.__class__.__name__)
      if not isinstance(sections, dict):
          return
      for part in sections:
        s = sections[part]
        if not (s.has_key("ip") and s.has_key("user")):
          print "SSH Configuration: Ignoring section %s" % s
          continue
        ip = s["ip"]
        user = s["user"]
        port = s["port"]
        last_time = s["last_time"]
        passwd = s["passwd"]

        self.cmd_list.append({ 'ip' : ip, 'user' : user, 
                               'port' : port,'last_time':last_time ,'passwd':passwd 
                            })
예제 #21
0
    def __init__(self):
        plugin.MenuItem.__init__(self)
        self.config = Config()
        colorize_config = self.config.plugin_get_config(self.__class__.__name__)
        if not colorize_config:
            colorize_config = self.presets
        self.color_set = []
        counter = 0
        if colorize_config:
            while colorize_config.get('color' + str(counter)):
                self.color_set.append(colorize_config.get('color' + str(counter)))
                counter += 1

        print self.color_set
예제 #22
0
    def __init__(self):
        self.terminator = Terminator()
        self.terminator.register_launcher_window(self)

        self.config = Config()
        self.config.base.reload()
        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 as ex:
            print("Failed to find layoutlauncher.glade")
            print(ex)
            return

        self.builder.add_from_string(gladedata)
        self.window = self.builder.get_object('layoutlauncherwin')

        icon_theme = Gtk.IconTheme.get_default()
        if icon_theme.lookup_icon('terminator-layout', 48, 0):
            self.window.set_icon_name('terminator-layout')
        else:
            dbg('Unable to load Terminator layout launcher icon')
            icon = self.window.render_icon(Gtk.STOCK_DIALOG_INFO,
                                           Gtk.IconSize.BUTTON)
            self.window.set_icon(icon)

        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()
예제 #23
0
    def __init__(self, title, notebook):
        """Class initialiser"""
        GObject.GObject.__init__(self)

        self.notebook = notebook
        self.terminator = Terminator()
        self.config = Config()

        self.label = EditableLabel(title)
        self.update_angle()

        self.pack_start(self.label, True, True, 0)

        self.update_button()
        self.show_all()
예제 #24
0
    def _save_config(self):
      log_debug("_save_config")
      config = Config()
      config.plugin_del_config(self.__class__.__name__)
      i = 0
      for ssh_conf in self.cmd_list :
        ip = ssh_conf['ip']
        user = ssh_conf['user']
        port = ssh_conf['port']
        last_time = ssh_conf['last_time']
        passwd = ssh_conf['passwd']

        item = { 'ip': ip, 'user': user, 'port': port, 'last_time': last_time, 'passwd': passwd}
        ssh_key = user+"@"+ip
        config.plugin_set(self.__class__.__name__, ssh_key, item)

        i = i + 1
      config.save()
예제 #25
0
    def _save_config(self):
      config = Config()
      config.plugin_del_config(self.__class__.__name__)
      i = 0
      for command in [ self.cmd_list[key] for key in sorted(self.cmd_list.keys()) ] :
        enabled = command['enabled']
        name = command['name']
        command = command['command']
       
        item = {}
        item['enabled'] = enabled
        item['name'] = name
        item['command'] = command
        item['position'] = i

        config.plugin_set(self.__class__.__name__, name, item)
        i = i + 1
      config.save()
예제 #26
0
    def _save_config(self):
        config = Config()
        config.plugin_del_config(self.__class__.__name__)
        i = 0
        for command in [
                self.cmd_list[key] for key in sorted(self.cmd_list.keys())
        ]:
            enabled = command['enabled']
            regexp = command['regexp']
            command = command['command']

            item = {}
            item['enabled'] = enabled
            item['regexp'] = regexp
            item['command'] = command
            item['position'] = i

            config.plugin_set(self.__class__.__name__, regexp, item)
            i = i + 1
        config.save()
        self._load_configured_handlers()
예제 #27
0
    def _save_config(self):
      config = Config()
      config.plugin_del_config(self.__class__.__name__)
      i = 0
      for command in [ self.cmd_list[key] for key in sorted(self.cmd_list.keys()) ] :
        enabled = command['enabled']
        name = command['name']
        command = command['command']
       
        item = {}
        item['enabled'] = enabled
        item['name'] = name
        item['command'] = command
        item['position'] = i

        config.plugin_set(self.__class__.__name__, name, item)
        i = i + 1
      config.save()
예제 #28
0
    def _save_config(self):
        config = Config()
        i = 0
        length = len(self.cmd_list)
        while i < length:
            name = self.cmd_list[i]['name']
            command = self.cmd_list[i]['command']

            item = {}
            item['name'] = name
            item['command'] = command

            config.plugin_set(self.__class__.__name__, name, item)
            config.save()
            i = i + 1
예제 #29
0
    def load_plugins(self, testing=False):
        """Load all plugins present in the plugins/ directory in our module"""
        if self.done:
            dbg('PluginRegistry::load_plugins: Already loaded')
            return

        config = Config()

        for plugindir in self.path:
            sys.path.insert(0, plugindir)
            try:
                files = os.listdir(plugindir)
            except OSError:
                sys.path.remove(plugindir)
                continue
            for plugin in files:
                if plugin == '__init__.py':
                    continue
                pluginpath = os.path.join(plugindir, plugin)
                if os.path.isfile(pluginpath) and plugin[-3:] == '.py':
                    dbg('PluginRegistry::load_plugins: Importing plugin %s' %
                        plugin)
                    try:
                        module = __import__(plugin[:-3], None, None, [''])
                        for item in getattr(module, 'AVAILABLE'):
                            if item not in self.available_plugins.keys():
                                func = getattr(module, item)
                                self.available_plugins[item] = func

                            if not testing and item not in config[
                                    'enabled_plugins']:
                                dbg('plugin %s not enabled, skipping' % item)
                                continue
                            if item not in self.instances:
                                self.instances[item] = func()
                    except Exception as ex:
                        err('PluginRegistry::load_plugins: Importing plugin %s \
failed: %s' % (plugin, ex))

        self.done = True
예제 #30
0
class JiraUrlPlugin(plugin.URLHandler):
    capabilties = ["url_handler"]
    handler_name = "jira_ticket"
    config = None
    plugin_name = "JiraUrlPlugin"

    def __init__(self):
        self.config = Config()

        if self.config.plugin_get_config(self.plugin_name) is None:
            for key, value in CONFIG_DEFAULTS.iteritems():
                self.config.plugin_set(self.plugin_name, key, value)
            self.config.save()

        self.match = self.config.plugin_get(self.plugin_name, "match")
        self.jira_url = self.config.plugin_get(self.plugin_name, "jira_url")


    def callback(self, url):
        if not (self.match or self.jira_url):
            return

        for item in re.findall(self.match, url):
            return("%s/%s" % (self.jira_url, item))
예제 #31
0
class ClonedSplittingMenu(plugin.MenuItem):
    capabilities = ['terminal_menu']
    config = Config()
    maker = Factory()

    def __init__(self):
        myconfig = self.config.plugin_get_config(self.__class__.__name__)
        # Now extract valid data from sections{}

    def callback(self, menuitems, menu, terminal):
        mhor = gtk.MenuItem('Clone Horizontally')
        mvert = gtk.MenuItem('Clone Vertically')

        mhor.connect('activate', self.clone_session, True, terminal)
        mvert.connect('activate', self.clone_session, False, terminal)

        menuitems.append(mhor)
        menuitems.append(mvert)

    def clone_session(self, menuitem, is_horizontal, terminal):
        container = self.get_terminal_container(terminal)
        if container:
            self.register_signals(container, terminal)

            cmd = self.get_terminal_cmd(terminal)
            cwd = terminal.terminator.pid_cwd(terminal.pid)

            sibling = ClonableTerminal()
            sibling.set_cwd(cwd)
            sibling.spawn_child_with_command(cmd)
            terminal.emit(
                'split-horiz-clone' if is_horizontal else 'split-vert-clone',
                cwd, sibling)
        else:
            terminal.emit('split-horiz' if is_horizontal else 'split-vert',
                          cwd)

    def get_terminal_container(self, terminal, container=None):
        terminator = Terminator()
        if not container:
            for window in terminator.windows:
                owner = self.get_terminal_container(terminal, window)
                if owner: return owner
        else:
            for child in container.get_children():
                if isinstance(child, Terminal) and child == terminal:
                    return container
                if isinstance(child, Container):
                    owner = self.get_terminal_container(terminal, child)
                    if owner: return owner

    def register_signals(self, container, terminal):
        container.signals.append({
            'name':
            'split-horiz-clone',
            'flags':
            gobject.SIGNAL_RUN_LAST,
            'return_type':
            gobject.TYPE_NONE,
            'param_types': (gobject.TYPE_STRING, gobject.TYPE_OBJECT)
        })

        container.signals.append({
            'name':
            'split-vert-clone',
            'flags':
            gobject.SIGNAL_RUN_LAST,
            'return_type':
            gobject.TYPE_NONE,
            'param_types': (gobject.TYPE_STRING, gobject.TYPE_OBJECT)
        })

        container.register_signals(terminal)

        container.connect_child(terminal, 'split-horiz-clone',
                                self.split_horiz)
        container.connect_child(terminal, 'split-vert-clone', self.split_vert)

    def split_horiz(self, terminal, cwd=None, sibling=None):
        container = self.get_terminal_container(terminal)
        return (container.split_axis(terminal, True, cwd, sibling))

    def split_vert(self, terminal, cwd=None, sibling=None):
        container = self.get_terminal_container(terminal)
        return (container.split_axis(terminal, False, cwd, sibling))

    def get_terminal_cmd(self, terminal):
        raw = subprocess.Popen(
            ['ps', '--no-headers', '-p',
             str(terminal.pid), '-o', 'command'],
            stdout=subprocess.PIPE)
        ps_line = subprocess.check_output(['head', '-1'],
                                          stdin=raw.stdout).strip()
        if ps_line and ps_line.strip().startswith('ssh'):
            return ps_line.strip()

        raw = subprocess.Popen([
            'ps', '--no-headers', '--ppid',
            str(terminal.pid), '-o', 'command'
        ],
                               stdout=subprocess.PIPE)
        ps_lines = subprocess.check_output(
            ['head', '-100'], stdin=raw.stdout).strip().split('\n')
        for ps_line in ps_lines:
            if ps_line.strip().startswith('ssh'):
                return ps_line.strip()

    def log(self, name, obj):
        with open('/tmp/log', 'a') as f:
            f.write('%s:' % name)
            f.write(str(obj))
            f.write(': done\n')
예제 #32
0
import terminatorlib.plugin as plugin
from terminatorlib.translation import _
from terminatorlib.util import err, dbg
from terminatorlib.version import APP_NAME

try:
    gi.require_version('Notify', '0.7')
    from gi.repository import Notify
    # Every plugin you want Terminator to load *must* be listed in 'AVAILABLE'
    # This is inside this try so we only make the plugin available if pynotify
    #  is present on this computer.
    AVAILABLE = ['ActivityWatch', 'InactivityWatch']
except (ImportError, ValueError):
    err('ActivityWatch plugin unavailable as we cannot import Notify')

config = Config()
inactive_period = float(
    config.plugin_get('InactivityWatch', 'inactive_period', 10.0))
watch_interval = int(
    config.plugin_get('InactivityWatch', 'watch_interval', 5000))
hush_period = float(config.plugin_get('ActivityWatch', 'hush_period', 10.0))


class ActivityWatch(plugin.MenuItem):
    """Add custom commands to the terminal menu"""
    capabilities = ['terminal_menu']
    watches = None
    last_notifies = None
    timers = None

    def __init__(self):
예제 #33
0
def parse_options():
    """Parse the command line options"""
    usage = "usage: %prog [options]"

    is_x_terminal_emulator = os.path.basename(
        sys.argv[0]) == 'x-terminal-emulator'

    parser = OptionParser(usage)

    parser.add_option('-v',
                      '--version',
                      action='store_true',
                      dest='version',
                      help=_('Display program version'))
    parser.add_option('-m',
                      '--maximise',
                      action='store_true',
                      dest='maximise',
                      help=_('Maximize the window'))
    parser.add_option('-f',
                      '--fullscreen',
                      action='store_true',
                      dest='fullscreen',
                      help=_('Make the window fill the screen'))
    parser.add_option('-b',
                      '--borderless',
                      action='store_true',
                      dest='borderless',
                      help=_('Disable window borders'))
    parser.add_option('-H',
                      '--hidden',
                      action='store_true',
                      dest='hidden',
                      help=_('Hide the window at startup'))
    parser.add_option('-T',
                      '--title',
                      dest='forcedtitle',
                      help=_('Specify a title for the window'))
    parser.add_option('--geometry',
                      dest='geometry',
                      type='string',
                      help=_(
                          'Set the preferred size and position of the window'
                          '(see X man page)'))
    if not is_x_terminal_emulator:
        parser.add_option(
            '-e',
            '--command',
            dest='command',
            help=_('Specify a command to execute inside the terminal'))
    else:
        parser.add_option(
            '--command',
            dest='command',
            help=_('Specify a command to execute inside the terminal'))
        parser.add_option(
            '-e',
            '--execute2',
            dest='execute',
            action='callback',
            callback=execute_cb,
            help=_('Use the rest of the command line as a command to '
                   'execute inside the terminal, and its arguments'))
    parser.add_option('-g',
                      '--config',
                      dest='config',
                      help=_('Specify a config file'))
    parser.add_option(
        '-x',
        '--execute',
        dest='execute',
        action='callback',
        callback=execute_cb,
        help=_('Use the rest of the command line as a command to execute '
               'inside the terminal, and its arguments'))
    parser.add_option('--working-directory',
                      metavar='DIR',
                      dest='working_directory',
                      help=_('Set the working directory'))
    parser.add_option('-i',
                      '--icon',
                      dest='forcedicon',
                      help=_('Set a custom \
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=_('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',
                      help=_('Disable DBus'))
    parser.add_option(
        '-d',
        '--debug',
        action='count',
        dest='debug',
        help=_('Enable debugging information (twice for debug server)'))
    parser.add_option(
        '--debug-classes',
        action='store',
        dest='debug_classes',
        help=_('Comma separated list of classes to limit debugging to'))
    parser.add_option(
        '--debug-methods',
        action='store',
        dest='debug_methods',
        help=_('Comma separated list of methods to limit debugging to'))
    parser.add_option(
        '--new-tab',
        action='store_true',
        dest='new_tab',
        help=_('If Terminator is already running, just open a new tab'))
    for item in [
            '--sm-client-id', '--sm-config-prefix', '--screen', '-n',
            '--no-gconf'
    ]:
        parser.add_option(item,
                          dest='dummy',
                          action='store',
                          help=SUPPRESS_HELP)

    global options
    (options, args) = parser.parse_args()
    if len(args) != 0:
        parser.error('Additional unexpected arguments found: %s' % args)

    if options.version:
        print('%s %s' % (APP_NAME, APP_VERSION))
        sys.exit(0)

    if options.debug_classes or options.debug_methods:
        if not options.debug > 0:
            options.debug = 1

    if options.debug:
        terminatorlib.util.DEBUG = True
        if options.debug > 1:
            terminatorlib.util.DEBUGFILES = True
        if options.debug_classes:
            classes = options.debug_classes.split(',')
            for item in classes:
                terminatorlib.util.DEBUGCLASSES.append(item.strip())
        if options.debug_methods:
            methods = options.debug_methods.split(',')
            for item in methods:
                terminatorlib.util.DEBUGMETHODS.append(item.strip())

    if options.working_directory:
        if os.path.exists(os.path.expanduser(options.working_directory)):
            options.working_directory = os.path.expanduser(
                options.working_directory)
            os.chdir(options.working_directory)
        else:
            err('OptionParse::parse_options: %s does not exist' %
                options.working_directory)
            options.working_directory = ''

    if options.layout is None:
        options.layout = 'default'

    configobj = Config()
    if options.profile and options.profile not in configobj.list_profiles():
        options.profile = None

    configobj.options_set(options)

    if terminatorlib.util.DEBUG == True:
        dbg('OptionParse::parse_options: command line options: %s' % options)

    return options
예제 #34
0
import terminatorlib.plugin as plugin
from terminatorlib.translation import _
from terminatorlib.util import err, dbg
from terminatorlib.version import APP_NAME

try:
    gi.require_version('Notify', '0.7')
    from gi.repository import Notify
    # Every plugin you want Terminator to load *must* be listed in 'AVAILABLE'
    # This is inside this try so we only make the plugin available if pynotify
    #  is present on this computer.
    AVAILABLE = ['ActivityWatch', 'InactivityWatch']
except ImportError:
    err(_('ActivityWatch plugin unavailable: please install python-notify'))

config = Config()
inactive_period = float(config.plugin_get('InactivityWatch', 'inactive_period',
                                        10.0))
watch_interval = int(config.plugin_get('InactivityWatch', 'watch_interval',
                                       5000))
hush_period = float(config.plugin_get('ActivityWatch', 'hush_period',
                                        10.0))

class ActivityWatch(plugin.MenuItem):
    """Add custom commands to the terminal menu"""
    capabilities = ['terminal_menu']
    watches = None
    last_notifies = None
    timers = None

    def __init__(self):
class Online_Servers(plugin.MenuItem):
    capabilities = ['terminal_menu']
    config_file = os.path.join(get_config_dir(), 'online_Servers')

    def __init__(self):
        self.config = Config()
        if not isinstance(
            self.config.plugin_get_config(
                self.__class__.__name__), dict):
            self.config.plugin_set_config(self.__class__.__name__, {})
            self.config.save()

        self._authorization = dict(Authorization='Bearer ' + TOKEN)
        self._base_api_url = 'https://api.online.net/api/v1'
        self._servers_infos_file_name = '/tmp/online_servers_infos'

    def callback(self, menuitems, menu, terminal):
        item = gtk.MenuItem('Serveurs online.net')
        menuitems.append(item)

        submenu = gtk.Menu()
        item.set_submenu(submenu)

        menuitem = gtk.MenuItem('Préferences')
        menuitem.connect('activate', self.settings)
        submenu.append(menuitem)
        submenu.append(gtk.SeparatorMenuItem())
        for server in self._load_servers_infos():
            config = self.config.plugin_get_config(self.__class__.__name__)
            if server['hostname'] in config:
                port = config[server['hostname']]['port'] if config[server['hostname']]['port'] != '' else '22'
                user = config[server['hostname']]['user'] + '@' if config[server['hostname']]['user'] != '' else ''
                if config[server['hostname']]['iface'] == 'private':
                    ip = server['ippriv']
                else:
                    ip = server['ippub']
            else:
                port = 22
                user = ''
                ip = server['ippub']
            menuitem = gtk.MenuItem(server['hostname'])
            menuitem.connect(
                'activate', self._execute,
                {'terminal' : terminal, 'command' : 'ssh -p {} {}{}'.format(
                    port, user, ip)})
            submenu.append(menuitem)

        menuitems.append(submenu)

    def settings(self, widget):
        dbox = gtk.Dialog(
            'Configuration', None, gtk.DIALOG_MODAL,
            (gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT))

        servers_list = gtk.ListStore(str)

        def serverList(widget=None, overwrite=False):
            servers_list.clear()
            for server in self._load_servers_infos(overwrite=overwrite):
                servers_list.append([server['hostname']])

        serverList()
        tree = gtk.TreeView(servers_list)
        selection = tree.get_selection()
        selection.set_mode(gtk.SELECTION_SINGLE)

        renderer = gtk.CellRendererText()
        column = gtk.TreeViewColumn("Serveurs", renderer, text=0)
        tree.append_column(column)

        button_box = gtk.VBox()
        button_edit = gtk.Button('Modifier', stock=gtk.STOCK_EDIT)
        button_edit.set_sensitive(False)
        button_edit.connect('clicked', self._edit, tree)
        selection.connect("changed", self._on_selection_changed, button_edit)

        button_refresh = gtk.Button('Rafraichir')
        button_refresh.connect('clicked', serverList, True)

        HBox = gtk.HBox()
        HBox.pack_start(tree)
        button_box.pack_start(button_edit, False, False)
        button_box.pack_start(button_refresh, False, False)
        HBox.pack_start(button_box)
        dbox.vbox.pack_start(HBox)
        dbox.show_all()

        if dbox.run() == gtk.RESPONSE_REJECT:
            dbox.destroy()

        return

    def _on_selection_changed(self, selection, data=None):
        data.set_sensitive(True)
        return

    def _edit(self, button, treeview):
        selection = treeview.get_selection()
        (store, iter) = selection.get_selected()
        selected_value = store.get_value(iter, 0)
        config = self.config.plugin_get_config(
            self.__class__.__name__)
        in_config = False if selected_value not in config else True

        dialog = gtk.Dialog(
            'Paramètres liés au serveur', None, gtk.DIALOG_MODAL,
            (
                gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT,
                gtk.STOCK_OK, gtk.RESPONSE_ACCEPT
                )
            )

        table = gtk.Table(1, 3)

        label = gtk.Label('Interface:')
        table.attach(label, 0, 1, 0, 1)
        r1 = gtk.RadioButton(None, label='Privée')
        r2 = gtk.RadioButton(r1, label='Publique')
        if in_config:
            if config[selected_value]['iface'] == 'private':
                r1.set_active(1)
            else:
                r2.set_active(1)
        else:
            r2.set_active(1)

        table.attach(r1, 1, 2, 0, 1)
        table.attach(r2, 2, 3, 0, 1)

        dialog.vbox.pack_start(table)

        table = gtk.Table(1, 2)
        label = gtk.Label('Utilisateur:')
        table.attach(label, 0, 1, 1, 2)
        user = gtk.Entry()
        if in_config:
            user.set_text(config[selected_value]['user'])
        else:
            user.set_text('')
        table.attach(user, 1, 2, 1, 2)

        label = gtk.Label('Port:')
        table.attach(label, 0, 1, 2, 3)
        port = gtk.Entry()
        if in_config:
            port.set_text(config[selected_value]['port'])
        else:
            port.set_text('')
        table.attach(port, 1, 2, 2, 3)

        dialog.vbox.pack_start(table)
        dialog.show_all()

        data = dict()
        run = dialog.run()
        if run == gtk.RESPONSE_REJECT:
            dialog.destroy()

        if run == gtk.RESPONSE_ACCEPT:
            if r1.get_active():
                data['iface'] = 'private'
            else:
                data['iface'] = 'public'

            data['user'] = user.get_text()
            data['port'] = port.get_text()

            if in_config:
                self.config.plugin_set_config(
                    self.__class__.__name__, {})
                self.config.save()
                config[selected_value] = data
            else:
                config.update({selected_value: data})
            self.config.plugin_set_config(
                self.__class__.__name__, config)

            self.config.save()

            dialog.destroy()

    def _execute(self, widget, data):
        data['terminal'].vte.feed_child(data['command'] + '\n')

    @property
    def _servers_list(self):
        url = self._base_api_url + '/server'
        servers = requests.get(
            url, headers=self._authorization)

        servers = [server.strip(url) for server in loads(servers.text)]

        return servers

    @property
    def _servers_infos(self):
        servers = list()
        servers_list = self._servers_list
        for i, server in enumerate(servers_list):
            request = requests.get(
                self._base_api_url + '/server/' + server,
                headers=self._authorization)
            servers.append(loads(request.text))

        for i, server in enumerate(list(servers)):
            servers[i] = dict(
                hostname=server['hostname'], ippub=server['network']['ip'][0] if server['network']['ip'] != [] else '',
                ippriv=server['network']['private'][0] if server['network']['private'] != [] else '')

        return servers

    def _save_servers_infos(self):
        infos = self._servers_infos
        pickle.dump(infos, open(self._servers_infos_file_name, 'wb+'))

        return infos

    def _load_servers_infos(self, overwrite=False):

        if os.path.isfile(self._servers_infos_file_name) and not overwrite:
            servers = pickle.load(open(self._servers_infos_file_name, 'rb'))
        else:
            servers = self._save_servers_infos()

        return servers
예제 #36
0
 def __init__(self, terminal):
     """Class initialiser"""
     self.terminal = terminal
     self.terminator = Terminator()
     self.config = Config()
예제 #37
0
class TerminalPopupMenu(object):
    """Class implementing the Terminal context menu"""
    terminal = None
    terminator = None
    config = None

    def __init__(self, terminal):
        """Class initialiser"""
        self.terminal = terminal
        self.terminator = Terminator()
        self.config = Config()

    def show(self, widget, event=None):
        """Display the context menu"""
        terminal = self.terminal

        menu = Gtk.Menu()
        self.popup_menu = menu
        url = None
        button = None
        time = None

        self.config.set_profile(terminal.get_profile())

        if event:
            url = terminal.vte.match_check_event(event)
            button = event.button
            time = event.time
        else:
            time = 0
            button = 3

        if url and url[0]:
            dbg("URL matches id: %d" % url[1])
            if not url[1] in terminal.matches.values():
                err("Unknown URL match id: %d" % url[1])
                dbg("Available matches: %s" % terminal.matches)

            nameopen = None
            namecopy = None
            if url[1] == terminal.matches['email']:
                nameopen = _('_Send email to...')
                namecopy = _('_Copy email address')
            elif url[1] == terminal.matches['voip']:
                nameopen = _('Ca_ll VoIP address')
                namecopy = _('_Copy VoIP address')
            elif url[1] in terminal.matches.values():
                # This is a plugin match
                for pluginname in terminal.matches:
                    if terminal.matches[pluginname] == url[1]:
                        break

                dbg("Found match ID (%d) in terminal.matches plugin %s" %
                    (url[1], pluginname))
                registry = PluginRegistry()
                registry.load_plugins()
                plugins = registry.get_plugins_by_capability('url_handler')
                for urlplugin in plugins:
                    if urlplugin.handler_name == pluginname:
                        dbg("Identified matching plugin: %s" %
                            urlplugin.handler_name)
                        nameopen = _(urlplugin.nameopen)
                        namecopy = _(urlplugin.namecopy)
                        break

            if not nameopen:
                nameopen = _('_Open link')
            if not namecopy:
                namecopy = _('_Copy address')

            icon = Gtk.Image.new_from_stock(Gtk.STOCK_JUMP_TO,
                                            Gtk.IconSize.MENU)
            item = Gtk.ImageMenuItem.new_with_mnemonic(nameopen)
            item.set_property('image', icon)
            item.connect('activate', lambda x: terminal.open_url(url, True))
            menu.append(item)

            item = Gtk.MenuItem.new_with_mnemonic(namecopy)
            item.connect(
                'activate', lambda x: terminal.clipboard.set_text(
                    terminal.prepare_url(url), len(terminal.prepare_url(url))))
            menu.append(item)

            menu.append(Gtk.SeparatorMenuItem())

        item = Gtk.ImageMenuItem.new_with_mnemonic(_('_Copy'))
        item.connect('activate', lambda x: terminal.vte.copy_clipboard())
        item.set_sensitive(terminal.vte.get_has_selection())
        menu.append(item)

        item = Gtk.ImageMenuItem.new_with_mnemonic(_('_Paste'))
        item.connect('activate', lambda x: terminal.paste_clipboard())
        menu.append(item)

        menu.append(Gtk.SeparatorMenuItem())

        if not terminal.is_zoomed():
            item = Gtk.ImageMenuItem.new_with_mnemonic(
                _('Split H_orizontally'))
            image = Gtk.Image()
            image.set_from_icon_name(APP_NAME + '_horiz', Gtk.IconSize.MENU)
            item.set_image(image)
            if hasattr(item, 'set_always_show_image'):
                item.set_always_show_image(True)
            item.connect(
                'activate', lambda x: terminal.emit('split-horiz',
                                                    self.terminal.get_cwd()))
            menu.append(item)

            item = Gtk.ImageMenuItem.new_with_mnemonic(_('Split V_ertically'))
            image = Gtk.Image()
            image.set_from_icon_name(APP_NAME + '_vert', Gtk.IconSize.MENU)
            item.set_image(image)
            if hasattr(item, 'set_always_show_image'):
                item.set_always_show_image(True)
            item.connect(
                'activate',
                lambda x: terminal.emit('split-vert', self.terminal.get_cwd()))
            menu.append(item)

            item = Gtk.MenuItem.new_with_mnemonic(_('Open _Tab'))
            item.connect('activate',
                         lambda x: terminal.emit('tab-new', False, terminal))
            menu.append(item)

            if self.terminator.debug_address is not None:
                item = Gtk.MenuItem.new_with_mnemonic(_('Open _Debug Tab'))
                item.connect(
                    'activate',
                    lambda x: terminal.emit('tab-new', True, terminal))
                menu.append(item)

            menu.append(Gtk.SeparatorMenuItem())

        item = Gtk.ImageMenuItem.new_with_mnemonic(_('_Close'))
        item.connect('activate', lambda x: terminal.close())
        menu.append(item)

        menu.append(Gtk.SeparatorMenuItem())

        if not terminal.is_zoomed():
            sensitive = not terminal.get_toplevel() == terminal.get_parent()

            item = Gtk.MenuItem.new_with_mnemonic(_('_Zoom terminal'))
            item.connect('activate', terminal.zoom)
            item.set_sensitive(sensitive)
            menu.append(item)

            item = Gtk.MenuItem.new_with_mnemonic(_('Ma_ximize terminal'))
            item.connect('activate', terminal.maximise)
            item.set_sensitive(sensitive)
            menu.append(item)

            menu.append(Gtk.SeparatorMenuItem())
        else:
            item = Gtk.MenuItem.new_with_mnemonic(_('_Restore all terminals'))
            item.connect('activate', terminal.unzoom)
            menu.append(item)

            menu.append(Gtk.SeparatorMenuItem())

        if self.config['show_titlebar'] == False:
            item = Gtk.MenuItem.new_with_mnemonic(_('Grouping'))
            submenu = self.terminal.populate_group_menu()
            submenu.show_all()
            item.set_submenu(submenu)
            menu.append(item)
            menu.append(Gtk.SeparatorMenuItem())

        item = Gtk.CheckMenuItem.new_with_mnemonic(_('Show _scrollbar'))
        item.set_active(terminal.scrollbar.get_property('visible'))
        item.connect('toggled', lambda x: terminal.do_scrollbar_toggle())
        menu.append(item)

        if hasattr(Gtk, 'Builder'):  # VERIFY FOR GTK3: is this ever false?
            item = Gtk.MenuItem.new_with_mnemonic(_('_Preferences'))
            item.connect('activate', lambda x: PrefsEditor(self.terminal))
            menu.append(item)

        profilelist = sorted(self.config.list_profiles(), key=string.lower)

        if len(profilelist) > 1:
            item = Gtk.MenuItem.new_with_mnemonic(_('Profiles'))
            submenu = Gtk.Menu()
            item.set_submenu(submenu)
            menu.append(item)

            current = terminal.get_profile()

            group = None

            for profile in profilelist:
                profile_label = profile
                if profile_label == 'default':
                    profile_label = profile.capitalize()
                item = Gtk.RadioMenuItem(profile_label, group)
                if profile == current:
                    item.set_active(True)
                item.connect('activate', terminal.force_set_profile, profile)
                submenu.append(item)

        self.add_encoding_items(menu)

        try:
            menuitems = []
            registry = PluginRegistry()
            registry.load_plugins()
            plugins = registry.get_plugins_by_capability('terminal_menu')
            for menuplugin in plugins:
                menuplugin.callback(menuitems, menu, terminal)

            if len(menuitems) > 0:
                menu.append(Gtk.SeparatorMenuItem())

            for menuitem in menuitems:
                menu.append(menuitem)
        except Exception as ex:
            err('TerminalPopupMenu::show: %s' % ex)

        menu.show_all()
        menu.popup(None, None, None, None, button, time)

        return True

    def add_encoding_items(self, menu):
        """Add the encoding list to the menu"""
        terminal = self.terminal
        active_encodings = terminal.config['active_encodings']
        item = Gtk.MenuItem.new_with_mnemonic(_("Encodings"))
        menu.append(item)
        submenu = Gtk.Menu()
        item.set_submenu(submenu)
        encodings = TerminatorEncoding().get_list()
        encodings.sort(lambda x, y: cmp(x[2].lower(), y[2].lower()))

        current_encoding = terminal.vte.get_encoding()
        group = None

        if current_encoding not in active_encodings:
            active_encodings.insert(0, _(current_encoding))

        for encoding in active_encodings:
            if encoding == terminal.default_encoding:
                extratext = " (%s)" % _("Default")
            elif encoding == current_encoding and \
                 terminal.custom_encoding == True:
                extratext = " (%s)" % _("User defined")
            else:
                extratext = ""

            radioitem = Gtk.RadioMenuItem(_(encoding) + extratext, group)

            if encoding == current_encoding:
                radioitem.set_active(True)

            if group is None:
                group = radioitem

            radioitem.connect('activate', terminal.on_encoding_change,
                              encoding)
            submenu.append(radioitem)

        item = Gtk.MenuItem.new_with_mnemonic(_("Other Encodings"))
        submenu.append(item)
        #second level

        submenu = Gtk.Menu()
        item.set_submenu(submenu)
        group = None

        for encoding in encodings:
            if encoding[1] in active_encodings:
                continue

            if encoding[1] is None:
                label = "%s %s" % (encoding[2], terminal.vte.get_encoding())
            else:
                label = "%s %s" % (encoding[2], encoding[1])

            radioitem = Gtk.RadioMenuItem(label, group)
            if group is None:
                group = radioitem

            if encoding[1] == current_encoding:
                radioitem.set_active(True)

            radioitem.connect('activate', terminal.on_encoding_change,
                              encoding[1])
            submenu.append(radioitem)
예제 #38
0
class Terminator(Borg):
    """master object for the application"""

    windows = None
    launcher_windows = None
    windowtitle = None
    terminals = None
    groups = None
    config = None
    keybindings = None
    style_providers = None
    last_focused_term = None

    origcwd = None
    dbus_path = None
    dbus_name = None
    pid_cwd = None
    gnome_client = None
    debug_address = None
    ibus_running = None

    doing_layout = None
    layoutname = None
    last_active_window = None
    prelayout_windows = None

    groupsend = None
    groupsend_type = {'all': 0, 'group': 1, 'off': 2}

    cur_gtk_theme_name = None
    gtk_settings = None

    def __init__(self):
        """Class initialiser"""

        Borg.__init__(self, self.__class__.__name__)
        self.prepare_attributes()

    def prepare_attributes(self):
        """Initialise anything that isn't already"""

        if not self.windows:
            self.windows = []
        if not self.launcher_windows:
            self.launcher_windows = []
        if not self.terminals:
            self.terminals = []
        if not self.groups:
            self.groups = []
        if not self.config:
            self.config = Config()
        if self.groupsend == None:
            self.groupsend = self.groupsend_type[
                self.config['broadcast_default']]
        if not self.keybindings:
            self.keybindings = Keybindings()
            self.keybindings.configure(self.config['keybindings'])
        if not self.style_providers:
            self.style_providers = []
        if not self.doing_layout:
            self.doing_layout = False
        if not self.pid_cwd:
            self.pid_cwd = get_pid_cwd()
        if self.gnome_client is None:
            self.attempt_gnome_client()
        self.connect_signals()

    def connect_signals(self):
        """Connect all the gtk signals"""
        self.gtk_settings = Gtk.Settings().get_default()
        self.gtk_settings.connect('notify::gtk-theme-name',
                                  self.on_gtk_theme_name_notify)
        self.cur_gtk_theme_name = self.gtk_settings.get_property(
            'gtk-theme-name')

    def set_origcwd(self, cwd):
        """Store the original cwd our process inherits"""
        if cwd == '/':
            cwd = os.path.expanduser('~')
            os.chdir(cwd)
        self.origcwd = cwd

    def set_dbus_data(self, dbus_service):
        """Store the DBus bus details, if they are available"""
        if dbus_service:
            self.dbus_name = dbus_service.bus_name.get_name()
            self.dbus_path = dbus_service.bus_path

    def attempt_gnome_client(self):
        """Attempt to find a GNOME Session to register with"""
        try:
            from gi.repository import Gnome
            self.gnome_program = Gnome.init(APP_NAME,
                                            APP_VERSION)  # VERIFY FOR GTK3
            self.gnome_client = Gnome.Ui.master_client()  # VERIFY FOR GTK3
            self.gnome_client.connect_to_session_manager()
            self.gnome_client.connect('save-yourself', self.save_yourself)
            self.gnome_client.connect('die', self.die)
            dbg('GNOME session support enabled and registered')
        except (ImportError, AttributeError):
            self.gnome_client = False
            dbg('GNOME session support not available')

    def save_yourself(self, *args):
        """Save as much state as possible for the session manager"""
        dbg('preparing session manager state')
        # FIXME: Implement this

    def die(self, *args):
        """Die at the hands of the session manager"""
        dbg('session manager asked us to die')
        # FIXME: Implement this

    def get_windows(self):
        """Return a list of windows"""
        return self.windows

    def register_window(self, window):
        """Register a new window widget"""
        if window not in self.windows:
            dbg('Terminator::register_window: registering %s:%s' %
                (id(window), type(window)))
            self.windows.append(window)

    def deregister_window(self, window):
        """de-register a window widget"""
        dbg('Terminator::deregister_window: de-registering %s:%s' %
            (id(window), type(window)))
        if window in self.windows:
            self.windows.remove(window)
        else:
            err('%s is not in registered window list' % window)

        if len(self.windows) == 0:
            # We have no windows left, we should exit
            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:
            dbg('Terminator::register_terminal: registering %s:%s' %
                (id(terminal), type(terminal)))
            self.terminals.append(terminal)

    def deregister_terminal(self, terminal):
        """De-register a terminal widget"""
        dbg('Terminator::deregister_terminal: de-registering %s:%s' %
            (id(terminal), type(terminal)))
        self.terminals.remove(terminal)

        if len(self.terminals) == 0:
            dbg('no terminals remain, destroying all windows')
            for window in self.windows:
                window.destroy()
        else:
            dbg('Terminator::deregister_terminal: %d terminals remain' %
                len(self.terminals))

    def find_terminal_by_uuid(self, uuid):
        """Search our terminals for one matching the supplied UUID"""
        dbg('searching self.terminals for: %s' % uuid)
        for terminal in self.terminals:
            dbg('checking: %s (%s)' % (terminal.uuid.urn, terminal))
            if terminal.uuid.urn == uuid:
                return terminal
        return None

    def find_window_by_uuid(self, uuid):
        """Search our terminals for one matching the supplied UUID"""
        dbg('searching self.terminals for: %s' % uuid)
        for window in self.windows:
            dbg('checking: %s (%s)' % (window.uuid.urn, window))
            if window.uuid.urn == uuid:
                return window
        return None

    def new_window(self, cwd=None, profile=None):
        """Create a window with a Terminal in it"""
        maker = Factory()
        window = maker.make('Window')
        terminal = maker.make('Terminal')
        if cwd:
            terminal.set_cwd(cwd)
        if profile and self.config['always_split_with_profile']:
            terminal.force_set_profile(None, profile)
        window.add(terminal)
        window.show(True)
        terminal.spawn_child()

        return (window, terminal)

    def create_layout(self, layoutname):
        """Create all the parts necessary to satisfy the specified layout"""
        layout = None
        objects = {}

        self.doing_layout = True
        self.last_active_window = None
        self.prelayout_windows = self.windows[:]

        layout = copy.deepcopy(self.config.layout_get_config(layoutname))
        if not layout:
            # User specified a non-existent layout. default to one Terminal
            err('layout %s not defined' % layout)
            self.new_window()
            return

        # Wind the flat objects into a hierarchy
        hierarchy = {}
        count = 0
        # Loop over the layout until we have consumed it, or hit 1000 loops.
        # This is a stupid artificial limit, but it's safe.
        while len(layout) > 0 and count < 1000:
            count = count + 1
            if count == 1000:
                err('hit maximum loop boundary. THIS IS VERY LIKELY A BUG')
            for obj in tuple(layout.keys()):
                if layout[obj]['type'].lower() == 'window':
                    hierarchy[obj] = {}
                    hierarchy[obj]['type'] = 'Window'
                    hierarchy[obj]['children'] = {}

                    # Copy any additional keys
                    for objkey in layout[obj].keys():
                        if layout[obj][
                                objkey] != '' and objkey not in hierarchy[obj]:
                            hierarchy[obj][objkey] = layout[obj][objkey]

                    objects[obj] = hierarchy[obj]
                    del layout[obj]
                else:
                    # Now examine children to see if their parents exist yet
                    if 'parent' not in layout[obj]:
                        err('Invalid object: %s' % obj)
                        del layout[obj]
                        continue
                    if layout[obj]['parent'] in objects:
                        # Our parent has been created, add ourselves
                        childobj = {}
                        childobj['type'] = layout[obj]['type']
                        childobj['children'] = {}

                        # Copy over any additional object keys
                        for objkey in layout[obj].keys():
                            if objkey not in childobj:
                                childobj[objkey] = layout[obj][objkey]

                        objects[layout[obj]
                                ['parent']]['children'][obj] = childobj
                        objects[obj] = childobj
                        del layout[obj]

        layout = hierarchy

        for windef in layout:
            if layout[windef]['type'] != 'Window':
                err('invalid layout format. %s' % layout)
                raise ValueError
            dbg('Creating a window')
            window, terminal = self.new_window()
            if 'position' in layout[windef]:
                parts = layout[windef]['position'].split(':')
                if len(parts) == 2:
                    window.move(int(parts[0]), int(parts[1]))
            if 'size' in layout[windef]:
                parts = layout[windef]['size']
                winx = int(parts[0])
                winy = int(parts[1])
                if winx > 1 and winy > 1:
                    window.resize(winx, winy)
            if 'title' in layout[windef]:
                window.title.force_title(layout[windef]['title'])
            if 'maximised' in layout[windef]:
                if layout[windef]['maximised'] == 'True':
                    window.ismaximised = True
                else:
                    window.ismaximised = False
                window.set_maximised(window.ismaximised)
            if 'fullscreen' in layout[windef]:
                if layout[windef]['fullscreen'] == 'True':
                    window.isfullscreen = True
                else:
                    window.isfullscreen = False
                window.set_fullscreen(window.isfullscreen)
            window.create_layout(layout[windef])

        self.layoutname = layoutname

    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 range(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()

        # Build list of new windows using prelayout list
        new_win_list = []
        for window in self.windows:
            if window not in self.prelayout_windows:
                new_win_list.append(window)

        # Make sure all new windows get bumped to the top
        for window in new_win_list:
            window.show()
            window.grab_focus()
            try:
                t = GdkX11.x11_get_server_time(window.get_window())
            except (TypeError, AttributeError):
                t = 0
            window.get_window().focus(t)

        # Awful workaround to be sure that the last focused window is actually the one focused.
        # Don't ask, don't tell policy on this. Even this is not 100%
        if self.last_active_window:
            window = self.find_window_by_uuid(self.last_active_window.urn)
            count = 0
            while count < 1000 and Gtk.events_pending():
                count += 1
                Gtk.main_iteration_do(False)
                window.show()
                window.grab_focus()
                try:
                    t = GdkX11.x11_get_server_time(window.get_window())
                except (TypeError, AttributeError):
                    t = 0
                window.get_window().focus(t)

        self.prelayout_windows = None

    def on_gtk_theme_name_notify(self, settings, prop):
        """Reconfigure if the gtk theme name changes"""
        new_gtk_theme_name = settings.get_property(prop.name)
        if new_gtk_theme_name != self.cur_gtk_theme_name:
            self.cur_gtk_theme_name = new_gtk_theme_name
            self.reconfigure()

    def reconfigure(self):
        """Update configuration for the whole application"""

        if self.style_providers != []:
            for style_provider in self.style_providers:
                Gtk.StyleContext.remove_provider_for_screen(
                    Gdk.Screen.get_default(), style_provider)
        self.style_providers = []

        # Force the window background to be transparent for newer versions of
        # GTK3. We then have to fix all the widget backgrounds because the
        # widgets theming may not render it's own background.
        css = """
            .terminator-terminal-window {
                background-color: alpha(@theme_bg_color,0); }

            .terminator-terminal-window .notebook.header,
            .terminator-terminal-window notebook header {
                background-color: @theme_bg_color; }

            .terminator-terminal-window .pane-separator {
                background-color: @theme_bg_color; }

            .terminator-terminal-window .terminator-terminal-searchbar {
                background-color: @theme_bg_color; }
            """

        # Fix several themes that put a borders, corners, or backgrounds around
        # viewports, making the titlebar look bad.
        css += """
            .terminator-terminal-window GtkViewport,
            .terminator-terminal-window viewport {
                border-width: 0px;
                border-radius: 0px;
                background-color: transparent; }
            """

        # Add per profile snippets for setting the background of the HBox
        template = """
            .terminator-profile-%s {
                background-color: alpha(%s, %s); }
            """
        profiles = self.config.base.profiles
        for profile in profiles.keys():
            if profiles[profile]['use_theme_colors']:
                # Create a dummy window/vte and realise it so it has correct
                # values to read from
                tmp_win = Gtk.Window()
                tmp_vte = Vte.Terminal()
                tmp_win.add(tmp_vte)
                tmp_win.realize()
                bgcolor = tmp_vte.get_style_context().get_background_color(
                    Gtk.StateType.NORMAL)
                bgcolor = "#{0:02x}{1:02x}{2:02x}".format(
                    int(bgcolor.red * 255), int(bgcolor.green * 255),
                    int(bgcolor.blue * 255))
                tmp_win.remove(tmp_vte)
                del tmp_vte
                del tmp_win
            else:
                bgcolor = Gdk.RGBA()
                bgcolor = profiles[profile]['background_color']
            if profiles[profile]['background_type'] == 'transparent':
                bgalpha = profiles[profile]['background_darkness']
            else:
                bgalpha = "1"

            munged_profile = "".join(
                [c if c.isalnum() else "-" for c in profile])
            css += template % (munged_profile, bgcolor, bgalpha)

        style_provider = Gtk.CssProvider()
        style_provider.load_from_data(css.encode('utf8'))
        self.style_providers.append(style_provider)

        # Attempt to load some theme specific stylistic tweaks for appearances
        usr_theme_dir = os.path.expanduser('~/.local/share/themes')
        (head, _tail) = os.path.split(borg.__file__)
        app_theme_dir = os.path.join(head, 'themes')

        theme_name = self.gtk_settings.get_property('gtk-theme-name')

        theme_part_list = ['terminator.css']
        if self.config[
                'extra_styling']:  # checkbox_style - needs adding to prefs
            theme_part_list.append('terminator_styling.css')
        for theme_part_file in theme_part_list:
            for theme_dir in [usr_theme_dir, app_theme_dir]:
                path_to_theme_specific_css = os.path.join(
                    theme_dir, theme_name, 'gtk-3.0/apps', theme_part_file)
                if os.path.isfile(path_to_theme_specific_css):
                    style_provider = Gtk.CssProvider()
                    style_provider.connect('parsing-error',
                                           self.on_css_parsing_error)
                    try:
                        style_provider.load_from_path(
                            path_to_theme_specific_css)
                    except GError:
                        # Hmmm. Should we try to provide GTK version specific files here on failure?
                        gtk_version_string = '.'.join([
                            str(Gtk.get_major_version()),
                            str(Gtk.get_minor_version()),
                            str(Gtk.get_micro_version())
                        ])
                        err('Error(s) loading css from %s into Gtk %s' %
                            (path_to_theme_specific_css, gtk_version_string))
                    self.style_providers.append(style_provider)
                    break

        # Size the GtkPaned splitter handle size.
        if self.config['handle_size'] in range(0, 21):
            css = '''.terminator-terminal-window GtkPaned,
            .terminator-terminal-window paned {{
            min-width: {0}px;
            min-height: {0}px; }}
            '''.format(self.config['handle_size'])
            style_provider = Gtk.CssProvider()
            style_provider.load_from_data(css.encode())
            self.style_providers.append(style_provider)

        # Apply the providers, incrementing priority so they don't cancel out
        # each other
        for idx in range(0, len(self.style_providers)):
            Gtk.StyleContext.add_provider_for_screen(
                Gdk.Screen.get_default(), self.style_providers[idx],
                Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION + idx)

        # Cause all the terminals to reconfigure
        for terminal in self.terminals:
            terminal.reconfigure()

        # Reparse our keybindings
        self.keybindings.configure(self.config['keybindings'])

        # Update tab position if appropriate
        maker = Factory()
        for window in self.windows:
            child = window.get_child()
            if maker.isinstance(child, 'Notebook'):
                child.configure()

    def on_css_parsing_error(self, provider, section, error, user_data=None):
        """Report CSS parsing issues"""
        file_path = section.get_file().get_path()
        line_no = section.get_end_line() + 1
        col_no = section.get_end_position() + 1
        err('%s, at line %d, column %d, of file %s' %
            (error.message, line_no, col_no, file_path))

    def create_group(self, name):
        """Create a new group"""
        if name not in self.groups:
            dbg('Terminator::create_group: registering group %s' % name)
            self.groups.append(name)

    def closegroupedterms(self, group):
        """Close all terminals in a group"""
        for terminal in self.terminals[:]:
            if terminal.group == group:
                terminal.close()

    def group_hoover(self):
        """Clean out unused groups"""

        if self.config['autoclean_groups']:
            inuse = []
            todestroy = []

            for terminal in self.terminals:
                if terminal.group:
                    if not terminal.group in inuse:
                        inuse.append(terminal.group)

            for group in self.groups:
                if not group in inuse:
                    todestroy.append(group)

            dbg('Terminator::group_hoover: %d groups, hoovering %d' %
                (len(self.groups), len(todestroy)))
            for group in todestroy:
                self.groups.remove(group)

    def group_emit(self, terminal, group, type, event):
        """Emit to each terminal in a group"""
        dbg('Terminator::group_emit: emitting a keystroke for group %s' %
            group)
        for term in self.terminals:
            if term != terminal and term.group == group:
                term.vte.emit(type, eventkey2gdkevent(event))

    def all_emit(self, terminal, type, event):
        """Emit to all terminals"""
        for term in self.terminals:
            if term != terminal:
                term.vte.emit(type, eventkey2gdkevent(event))

    def do_enumerate(self, widget, pad):
        """Insert the number of each terminal in a group, into that terminal"""
        if pad:
            numstr = '%0' + str(len(str(len(self.terminals)))) + 'd'
        else:
            numstr = '%d'

        terminals = []
        for window in self.windows:
            containers, win_terminals = enumerate_descendants(window)
            terminals.extend(win_terminals)

        for term in self.get_target_terms(widget):
            idx = terminals.index(term)
            term.feed(numstr % (idx + 1))

    def get_sibling_terms(self, widget):
        termset = []
        for term in self.terminals:
            if term.group == widget.group:
                termset.append(term)
        return termset

    def get_target_terms(self, widget):
        """Get the terminals we should currently be broadcasting to"""
        if self.groupsend == self.groupsend_type['all']:
            return self.terminals
        elif self.groupsend == self.groupsend_type['group']:
            if widget.group != None:
                return self.get_sibling_terms(widget)
        return [widget]

    def get_focussed_terminal(self):
        """iterate over all the terminals to find which, if any, has focus"""
        for terminal in self.terminals:
            if terminal.has_focus():
                return terminal
        return None

    def focus_changed(self, widget):
        """We just moved focus to a new terminal"""
        for terminal in self.terminals:
            terminal.titlebar.update(widget)
        return

    def focus_left(self, widget):
        self.last_focused_term = widget

    def describe_layout(self):
        """Describe our current layout"""
        layout = {}
        count = 0
        for window in self.windows:
            parent = ''
            count = window.describe_layout(count, parent, layout, 0)

        return layout
예제 #39
0
 def __init__(self):
     """Class initialiser"""
     self.children = []
     self.signals = []
     self.cnxids = Signalman()
     self.config = Config()
예제 #40
0
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#
#    You should have received a copy of the GNU General Public License
#    along with this program; if not, write to the Free Software
#    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  
#    USA

import gtk
import terminatorlib.plugin as plugin
from terminatorlib.translation import _
from os.path import isfile
from glib import timeout_add_seconds
import vte
from terminatorlib.config import Config
config = Config( )
base = config.base
profile = config.get_profile( )
idx = 0
import sys
import gobject
from gobject import GObject
sys.path.append('.')
from setter import Viewer
import os


class Fn( ):
    def __init__( self,profile,term=None ):
        self.profile = profile
예제 #41
0
class Colorize(plugin.MenuItem):
    """ Add custom command to the terminal menu"""
    capabilities = ['terminal_menu']
    config = None
    color_set = None
    ratio = 0.7

    presets = {
        'color0' : {
            'name'   : ' blue',
            'title_transmit_bg_color': '#0076C9'
        },
        'color1' : {
            'name'   : 'purple',
            'title_transmit_bg_color': '#B20DAC'
        },
        'color2' : {
            'name'   : 'yellow',
            'title_transmit_bg_color': '#EAF12A'
        },
        'color3' : {
            'name'   : 'green',
            'title_transmit_bg_color': '#50B20D'
        },
        'color4' : {
            'name'   : 'cyan',
            'title_transmit_bg_color': '#2DF2C1'
        }
    }

    def __init__(self):
        plugin.MenuItem.__init__(self)
        self.config = Config()
        colorize_config = self.config.plugin_get_config(self.__class__.__name__)
        if not colorize_config:
            colorize_config = self.presets
        self.color_set = []
        counter = 0
        if colorize_config:
            while colorize_config.get('color' + str(counter)):
                self.color_set.append(colorize_config.get('color' + str(counter)))
                counter += 1

        print self.color_set

    def callback(self, menuitems, menu, terminal):
        """ Add save menu item to log 'content'the menu"""
        vte_terminal = terminal.get_vte()

        change_color_item = gtk.MenuItem(_('Change color'))
        change_color_item.connect("activate", self.change_color, terminal)
        change_color_item.set_has_tooltip(True)
        change_color_item.set_tooltip_text("Change titlebar color of this terminal")

        menuitems.append(change_color_item)

        # sub menu

        pick_color_menu = gtk.Menu()

        counter = 1
        for color in self.color_set:
            if color.get('name'):
                suffix = color['name']
            else:
                suffix = str(counter)
            color_item = gtk.MenuItem(_('Color') + ' ' + suffix)
            color_item.connect("activate", self.pick_color, terminal, counter - 1)
            color_item.set_has_tooltip(True)
            color_item.set_tooltip_text("Set this color for current terminal")

            accel_group = gtk.AccelGroup()


            color_item.add_accelerator("activate", accel_group,
                                       ord(str(counter)), gtk.gdk.CONTROL_MASK | gtk.gdk.SHIFT_MASK, gtk.ACCEL_VISIBLE)


            pick_color_menu.append(color_item)
            counter += 1


        item = gtk.MenuItem(_('Pick color'))
        item.set_submenu(pick_color_menu)
        menuitems.append(item)

    def get_terminal_container(self, terminal, container=None):
        terminator = Terminator()
        if not container:
            for window in terminator.windows:
                owner = self.get_terminal_container(terminal, window)
                if owner:
                    return owner
        else:
            for child in container.get_children():
                if isinstance(child, Terminal) and child == terminal:
                    return container
                if isinstance(child, Container):
                    owner = self.get_terminal_container(terminal, child)
                if owner:
                    return owner


    def register_signals(self, container, terminal):
        container.signals.append({
            'name': 'pick-first-color',
            'flags': gobject.SIGNAL_RUN_LAST,
            'return_type': gobject.TYPE_NONE,
            'param_types': None
        })

        # container.signals.append({
        #     'name': 'split-vert-clone',
        #     'flags': gobject.SIGNAL_RUN_LAST,
        #     'return_type': gobject.TYPE_NONE,
        #     'param_types': None
        # })

        container.register_signals(terminal)

        container.connect_child(terminal, 'pick-first-color', self.pick_first_color)
        # container.connect_child(terminal, 'split-vert-clone', self.split_vert)

    def pick_first_color(self, terminal):
        self.pick_color(None, terminal, 1)

    def pick_color(self, _widget, terminal, index):
        print 'index', index
        self.set_titlebar_color(terminal, gtk.gdk.Color(self.color_set[index]['title_transmit_bg_color']))

    def change_color(self, _widget, Terminal):
        """ Handle menu item callback by saving text to a file"""
        color_dialog = gtk.ColorSelectionDialog("Pick new terminal's titlebar color")
        color_sel = color_dialog.colorsel

        # set previous colors
        previous_color = gtk.gdk.color_parse(Terminal.config['title_transmit_bg_color'])

        color_sel.set_previous_color(previous_color)
        color_sel.set_current_color(previous_color)
        color_sel.set_has_palette(True)


        response = color_dialog.run()
        if response == gtk.RESPONSE_OK:
            self.set_titlebar_color(Terminal, color_sel.get_current_color())

        color_dialog.destroy()


    def get_inactive_color(self, transmit_color):
        return gtk.gdk.Color(transmit_color.red_float * self.ratio,
                      transmit_color.green_float * self.ratio,
                      transmit_color.blue_float * self.ratio)


    def get_font_color(self, bg_color):
        lightness = (((bg_color.red_float * 299) +
                      (bg_color.green_float * 587) +
                      (bg_color.blue_float * 114)) /1000)


        new_fg_color = gtk.gdk.Color(0, 0, 0)

        if lightness < 0.5:
            new_fg_color = gtk.gdk.Color(65535, 65535, 65535)

        return new_fg_color


    def set_titlebar_color(self, Terminal, color):
        new_transmit_bg_color = color
        new_inactive_bg_color = self.get_inactive_color(new_transmit_bg_color)

        new_transmit_fg_color = self.get_font_color(new_transmit_bg_color)
        new_inactive_fg_color = self.get_font_color(new_inactive_bg_color)

        new_color_config = {
            'title_transmit_bg_color': new_transmit_bg_color.to_string(),
            'title_inactive_bg_color': new_inactive_bg_color.to_string(),
            'title_transmit_fg_color': new_transmit_fg_color.to_string(),
            'title_inactive_fg_color': new_inactive_fg_color.to_string()
        }

        new_config = ColorizeConfig(Terminal.titlebar.config, new_color_config)
        Terminal.titlebar.config = new_config
예제 #42
0
class Container(object):
    """Base class for Terminator Containers"""

    terminator = None
    immutable = None
    children = None
    config = None
    signals = None
    signalman = None

    def __init__(self):
        """Class initialiser"""
        self.children = []
        self.signals = []
        self.cnxids = Signalman()
        self.config = Config()

    def register_signals(self, widget):
        """Register gobject signals in a way that avoids multiple inheritance"""
        existing = GObject.signal_list_names(widget)
        for signal in self.signals:
            if signal['name'] in existing:
                dbg('Container:: skipping signal %s for %s, already exists' %
                    (signal['name'], widget))
            else:
                dbg('Container:: registering signal for %s on %s' %
                    (signal['name'], widget))
                try:
                    GObject.signal_new(signal['name'], widget, signal['flags'],
                                       signal['return_type'],
                                       signal['param_types'])
                except RuntimeError:
                    err('Container:: registering signal for %s on %s failed' %
                        (signal['name'], widget))

    def connect_child(self, widget, signal, handler, *args):
        """Register the requested signal and record its connection ID"""
        self.cnxids.new(widget, signal, handler, *args)
        return

    def disconnect_child(self, widget):
        """De-register the signals for a child"""
        self.cnxids.remove_widget(widget)

    def get_offspring(self):
        """Return a list of direct child widgets, if any"""
        return (self.children)

    def get_child_metadata(self, widget):
        """Return metadata that would be useful to recreate ourselves after our
        child is .remove()d and .add()ed"""
        return None

    def split_horiz(self, widget, cwd=None):
        """Split this container horizontally"""
        return (self.split_axis(widget, True, cwd))

    def split_vert(self, widget, cwd=None):
        """Split this container vertically"""
        return (self.split_axis(widget, False, cwd))

    def split_axis(self,
                   widget,
                   vertical=True,
                   cwd=None,
                   sibling=None,
                   siblinglast=None):
        """Default axis splitter. This should be implemented by subclasses"""
        raise NotImplementedError('split_axis')

    def rotate(self, widget, clockwise):
        """Rotate children in this container"""
        raise NotImplementedError('rotate')

    def add(self, widget, metadata=None):
        """Add a widget to the container"""
        raise NotImplementedError('add')

    def remove(self, widget):
        """Remove a widget from the container"""
        raise NotImplementedError('remove')

    def replace(self, oldwidget, newwidget):
        """Replace the child oldwidget with newwidget. This is the bare minimum
        required for this operation. Containers should override it if they have
        more complex requirements"""
        if not oldwidget in self.get_children():
            err('%s is not a child of %s' % (oldwidget, self))
            return
        self.remove(oldwidget)
        self.add(newwidget)

    def hoover(self):
        """Ensure we still have a reason to exist"""
        raise NotImplementedError('hoover')

    def get_children(self):
        """Return an ordered list of the children of this Container"""
        raise NotImplementedError('get_children')

    def closeterm(self, widget):
        """Handle the closure of a terminal"""
        try:
            if self.get_property('term_zoomed'):
                # We're zoomed, so unzoom and then start closing again
                dbg('Container::closeterm: terminal zoomed, unzooming')
                self.unzoom(widget)
                widget.close()
                return (True)
        except TypeError:
            pass

        if not self.remove(widget):
            dbg('Container::closeterm: self.remove() failed for %s' % widget)
            return (False)

        self.terminator.deregister_terminal(widget)
        widget.close()
        self.terminator.group_hoover()
        return (True)

    def resizeterm(self, widget, keyname):
        """Handle a keyboard event requesting a terminal resize"""
        raise NotImplementedError('resizeterm')

    def toggle_zoom(self, widget, fontscale=False):
        """Toggle the existing zoom state"""
        try:
            if self.get_property('term_zoomed'):
                self.unzoom(widget)
            else:
                self.zoom(widget, fontscale)
        except TypeError:
            err('Container::toggle_zoom: %s is unable to handle zooming, for \
            %s' % (self, widget))

    def zoom(self, widget, fontscale=False):
        """Zoom a terminal"""
        raise NotImplementedError('zoom')

    def unzoom(self, widget):
        """Unzoom a terminal"""
        raise NotImplementedError('unzoom')

    def construct_confirm_close(self, window, reqtype):
        """Create a confirmation dialog for closing things"""

        # skip this dialog if applicable
        if self.config['suppress_multiple_term_dialog']:
            return Gtk.ResponseType.ACCEPT

        dialog = Gtk.Dialog(_('Close?'), window, Gtk.DialogFlags.MODAL)
        dialog.set_resizable(False)

        dialog.add_button(Gtk.STOCK_CANCEL, Gtk.ResponseType.REJECT)
        c_all = dialog.add_button(Gtk.STOCK_CLOSE, Gtk.ResponseType.ACCEPT)
        c_all.get_children()[0].get_children()[0].get_children()[1].set_label(
            _('Close _Terminals'))

        primary = Gtk.Label(
            label=_('<big><b>Close multiple terminals?</b></big>'))
        primary.set_use_markup(True)
        primary.set_alignment(0, 0.5)
        if reqtype == 'window':
            label_text = _('This window has several terminals open. Closing \
the window will also close all terminals within it.')
        elif reqtype == 'tab':
            label_text = _('This tab has several terminals open. Closing \
the tab will also close all terminals within it.')
        else:
            label_text = ''
        secondary = Gtk.Label(label=label_text)
        secondary.set_line_wrap(True)

        labels = Gtk.VBox()
        labels.pack_start(primary, False, False, 6)
        labels.pack_start(secondary, False, False, 6)

        image = Gtk.Image.new_from_stock(Gtk.STOCK_DIALOG_WARNING,
                                         Gtk.IconSize.DIALOG)
        image.set_alignment(0.5, 0)

        box = Gtk.HBox()
        box.pack_start(image, False, False, 6)
        box.pack_start(labels, False, False, 6)
        dialog.vbox.pack_start(box, False, False, 12)

        checkbox = Gtk.CheckButton(_("Do not show this message next time"))
        dialog.vbox.pack_end(checkbox, True, True, 0)

        dialog.show_all()

        result = dialog.run()

        # set configuration
        self.config.base.reload()
        self.config['suppress_multiple_term_dialog'] = checkbox.get_active()
        self.config.save()

        dialog.destroy()

        return (result)

    def propagate_title_change(self, widget, title):
        """Pass a title change up the widget stack"""
        maker = Factory()
        parent = self.get_parent()
        title = widget.get_window_title()

        if maker.isinstance(self, 'Notebook'):
            self.update_tab_label_text(widget, title)
        elif maker.isinstance(self, 'Window'):
            self.title.set_title(widget, title)

        if maker.isinstance(parent, 'Container'):
            parent.propagate_title_change(widget, title)

    def get_visible_terminals(self):
        """Walk the widget tree to find all of the visible terminals. That is,
        any terminals which are not hidden in another Notebook pane"""
        if not hasattr(self, 'cached_maker'):
            self.cached_maker = Factory()
        maker = self.cached_maker
        terminals = {}

        for child in self.get_offspring():
            if not child:
                continue
            if maker.isinstance(child, 'Terminal'):
                terminals[child] = child.get_allocation()
            elif maker.isinstance(child, 'Container'):
                terminals.update(child.get_visible_terminals())
            else:
                err('Unknown child type %s' % type(child))

        return (terminals)

    def describe_layout(self, count, parent, global_layout, child_order):
        """Describe our current layout"""
        layout = {}
        maker = Factory()
        mytype = maker.type(self)
        if not mytype:
            err('unable to detemine own type. %s' % self)
            return ({})

        layout['type'] = mytype
        layout['parent'] = parent
        layout['order'] = child_order

        if hasattr(self, 'get_position'):
            position = self.get_position()
            if hasattr(position, '__iter__'):
                position = ':'.join([str(x) for x in position])
            layout['position'] = position

        if hasattr(self, 'ismaximised'):
            layout['maximised'] = self.ismaximised

        if hasattr(self, 'isfullscreen'):
            layout['fullscreen'] = self.isfullscreen

        if hasattr(self, 'ratio'):
            layout['ratio'] = self.ratio

        if hasattr(self, 'get_size'):
            layout['size'] = self.get_size()

        if hasattr(self, 'title'):
            layout['title'] = self.title.text

        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())
                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

        global_layout[name] = layout

        child_order = 0
        for child in self.get_children():
            if hasattr(child, 'describe_layout'):
                count = child.describe_layout(count, name, global_layout,
                                              child_order)
            child_order = child_order + 1

        return (count)

    def create_layout(self, layout):
        """Apply settings for our layout"""
        raise NotImplementedError('create_layout')
예제 #43
0
#!/usr/bin/env python
import os
import sys
from terminatorlib.config import Config
from terminatorlib.util import get_config_dir

class Opts(object):
    pass

opts = Opts()
opts.config = os.path.join(get_config_dir(), 'config')

config = Config()
config.options_set(opts)

# misc options
config['word_chars'] = '-A-Za-z0-9,./?%&_~'
config['scrollback_lines'] = 500000
config['scroll_on_output'] = False
config['use_system_font'] = False
config['font'] = 'Ubuntu Mono 9'

config.save()