예제 #1
0
    def save(self):
        """Save the config to a file"""
        dbg('ConfigBase::save: saving config')
        parser = ConfigObj()
        parser.indent_type = '  '

        for section_name in ['global_config', 'keybindings']:
            dbg('ConfigBase::save: Processing section: %s' % section_name)
            section = getattr(self, section_name)
            parser[section_name] = dict_diff(DEFAULTS[section_name], section)

        parser['profiles'] = {}
        for profile in self.profiles:
            dbg('ConfigBase::save: Processing profile: %s' % profile)
            parser['profiles'][profile] = dict_diff(
                DEFAULTS['profiles']['default'], self.profiles[profile])

        parser['layouts'] = {}
        for layout in self.layouts:
            dbg('ConfigBase::save: Processing layout: %s' % layout)
            parser['layouts'][layout] = self.layouts[layout]

        parser['plugins'] = {}
        for plugin in self.plugins:
            dbg('ConfigBase::save: Processing plugin: %s' % plugin)
            parser['plugins'][plugin] = self.plugins[plugin]

        config_dir = get_config_dir()
        if not os.path.isdir(config_dir):
            os.makedirs(config_dir)
        try:
            parser.write(open(self.command_line_options.config, 'w'))
        except Exception as ex:
            err('ConfigBase::save: Unable to save config: %s' % ex)
예제 #2
0
 def ensure_config_dir(self):
     """
     Set the directory, where our layouts are saved.
     We use terminator's config dir plus LayoutManager (most likely
     ~/.config/terminator/LayoutManager).
     """
     config_dir = self.config_dir or join(get_config_dir(), LAYOUTMANAGER_NAME)
     if not exists(config_dir):
         makedirs(config_dir)
     return config_dir
예제 #3
0
 def ensure_config_dir(self):
     """
     Set the directory, where our layouts are saved.
     We use terminator's config dir plus LayoutManager (most likely
     ~/.config/terminator/LayoutManager).
     """
     config_dir = self.config_dir or join(get_config_dir(),
                                          LAYOUTMANAGER_NAME)
     if not exists(config_dir):
         makedirs(config_dir)
     return config_dir
예제 #4
0
 def setConfigDir(self):
     """
     Set the directory, where our layouts are saved.
     We use terminator's config dir plus LayoutManager (most likley
     ~/.config/terminator/LayoutManager).
     """
     if self.configDir is None:
         configDir = join(get_config_dir(), LAYOUTMANAGER_NAME)
         if not exists(configDir):
             makedirs(configDir)
         self.configDir = configDir
예제 #5
0
 def prepare_attributes(self):
     """Prepare our attributes"""
     if not self.instances:
         self.instances = {}
     if not self.path:
         self.path = []
         (head, _tail) = os.path.split(borg.__file__)
         self.path.append(os.path.join(head, 'plugins'))
         self.path.append(os.path.join(get_config_dir(), 'plugins'))
         dbg(f'PluginRegistry::prepare_attributes: Plugin path: {self.path}')
     if not self.done:
         self.done = False
     if not self.available_plugins:
         self.available_plugins = {}
예제 #6
0
    def load(self):
        """Load configuration data from our various sources"""
        if self.loaded is True:
            dbg('ConfigBase::load: config already loaded')
            return

        self.config_filename = self.command_line_options.config or os.path.join(
            get_config_dir(), 'config.json')

        dbg('load config file: %s' % self.config_filename)

        configdata = {}
        self.get_default_config(configdata)
        try:
            with open(self.config_filename, mode='rt') as f:
                configdata.update(json.load(f))
        except FileNotFoundError as ex:
            err('ConfigBase::load: Unable to load %s (%s)' %
                (self.config_filename, ex))

        for section_name in self.sections:
            section = getattr(self, section_name)
            section.update(configdata.get(section_name, ()))

            #set default profile options
            if section_name == 'profiles':
                for profile in section.values():
                    for k, v in DEFAULTS['profiles']['default'].items():
                        if k not in profile:
                            profile[k] = v

            #set default layout options
            if section_name == 'layouts':
                for layouts in section.values():
                    for k, v in DEFAULTS['layouts']['default'].items():
                        if k not in layouts:
                            profile[k] = v

        self.loaded = True
예제 #7
0
class CustomCommandsMenu(plugin.MenuItem):
    """Add custom commands to the terminal menu"""
    capabilities = ['terminal_menu']
    cmd_list = {}
    conf_file = os.path.join(get_config_dir(), "custom_commands")

    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

    def callback(self, menuitems, menu, terminal):
        """Add our menu items to the menu"""
        item = Gtk.MenuItem.new_with_mnemonic(_('_Custom Commands'))
        menuitems.append(item)

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

        menuitem = Gtk.MenuItem.new_with_mnemonic(_('_Preferences'))
        menuitem.connect("activate", self.configure)
        submenu.append(menuitem)

        menuitem = Gtk.SeparatorMenuItem()
        submenu.append(menuitem)

        theme = Gtk.IconTheme.get_default()
        for command in [
                self.cmd_list[key] for key in sorted(self.cmd_list.keys())
        ]:
            if not command['enabled']:
                continue
            exe = command['command'].split(' ')[0]
            iconinfo = theme.choose_icon([exe], Gtk.IconSize.MENU,
                                         Gtk.IconLookupFlags.USE_BUILTIN)
            if iconinfo:
                image = Gtk.Image()
                image.set_from_icon_name(exe, Gtk.IconSize.MENU)
                menuitem = Gtk.ImageMenuItem(command['name'])
                menuitem.set_image(image)
            else:
                menuitem = Gtk.MenuItem(command["name"])
            terminals = terminal.terminator.get_target_terms(terminal)
            menuitem.connect("activate", self._execute, {
                'terminals': terminals,
                'command': command['command']
            })
            submenu.append(menuitem)

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

    def _execute(self, widget, data):
        command = data['command']
        if command[-1] != '\n':
            command = command + '\n'
        for terminal in data['terminals']:
            terminal.vte.feed_child(command, len(command))

    def configure(self, widget, data=None):
        ui = {}
        dbox = Gtk.Dialog(_("Custom Commands Configuration"), None,
                          Gtk.DialogFlags.MODAL,
                          (_("_Cancel"), Gtk.ResponseType.REJECT, _("_OK"),
                           Gtk.ResponseType.ACCEPT))

        icon_theme = Gtk.IconTheme.get_default()
        if icon_theme.lookup_icon('terminator-custom-commands', 48, 0):
            dbox.set_icon_name('terminator-custom-commands')
        else:
            dbg('Unable to load Terminator custom command icon')
            icon = dbox.render_icon(Gtk.STOCK_DIALOG_INFO, Gtk.IconSize.BUTTON)
            dbox.set_icon(icon)

        store = Gtk.ListStore(bool, str, str)

        for command in [
                self.cmd_list[key] for key in sorted(self.cmd_list.keys())
        ]:
            store.append(
                [command['enabled'], command['name'], command['command']])

        treeview = Gtk.TreeView(store)
        #treeview.connect("cursor-changed", self.on_cursor_changed, ui)
        selection = treeview.get_selection()
        selection.set_mode(Gtk.SelectionMode.SINGLE)
        selection.connect("changed", self.on_selection_changed, ui)
        ui['treeview'] = treeview

        renderer = Gtk.CellRendererToggle()
        renderer.connect('toggled', self.on_toggled, ui)
        column = Gtk.TreeViewColumn(_("Enabled"),
                                    renderer,
                                    active=CC_COL_ENABLED)
        treeview.append_column(column)

        renderer = Gtk.CellRendererText()
        column = Gtk.TreeViewColumn(_("Name"), renderer, text=CC_COL_NAME)
        treeview.append_column(column)

        renderer = Gtk.CellRendererText()
        column = Gtk.TreeViewColumn(_("Command"),
                                    renderer,
                                    text=CC_COL_COMMAND)
        treeview.append_column(column)

        scroll_window = Gtk.ScrolledWindow()
        scroll_window.set_size_request(500, 250)
        scroll_window.set_policy(Gtk.PolicyType.AUTOMATIC,
                                 Gtk.PolicyType.AUTOMATIC)
        scroll_window.add_with_viewport(treeview)

        hbox = Gtk.HBox()
        hbox.pack_start(scroll_window, True, True, 0)
        dbox.vbox.pack_start(hbox, True, True, 0)

        button_box = Gtk.VBox()

        button = Gtk.Button(_("Top"))
        button_box.pack_start(button, False, True, 0)
        button.connect("clicked", self.on_goto_top, ui)
        button.set_sensitive(False)
        ui['button_top'] = button

        button = Gtk.Button(_("Up"))
        button_box.pack_start(button, False, True, 0)
        button.connect("clicked", self.on_go_up, ui)
        button.set_sensitive(False)
        ui['button_up'] = button

        button = Gtk.Button(_("Down"))
        button_box.pack_start(button, False, True, 0)
        button.connect("clicked", self.on_go_down, ui)
        button.set_sensitive(False)
        ui['button_down'] = button

        button = Gtk.Button(_("Last"))
        button_box.pack_start(button, False, True, 0)
        button.connect("clicked", self.on_goto_last, ui)
        button.set_sensitive(False)
        ui['button_last'] = button

        button = Gtk.Button(_("New"))
        button_box.pack_start(button, False, True, 0)
        button.connect("clicked", self.on_new, ui)
        ui['button_new'] = button

        button = Gtk.Button(_("Edit"))
        button_box.pack_start(button, False, True, 0)
        button.set_sensitive(False)
        button.connect("clicked", self.on_edit, ui)
        ui['button_edit'] = button

        button = Gtk.Button(_("Delete"))
        button_box.pack_start(button, False, True, 0)
        button.connect("clicked", self.on_delete, ui)
        button.set_sensitive(False)
        ui['button_delete'] = button

        hbox.pack_start(button_box, False, True, 0)
        dbox.show_all()
        res = dbox.run()
        if res == Gtk.ResponseType.ACCEPT:
            self.update_cmd_list(store)
            self._save_config()
        dbox.destroy()
        return

    def update_cmd_list(self, store):
        iter = store.get_iter_first()
        self.cmd_list = {}
        i = 0
        while iter:
            (enabled, name, command) = store.get(iter, CC_COL_ENABLED,
                                                 CC_COL_NAME, CC_COL_COMMAND)
            self.cmd_list[i] = {
                'enabled': enabled,
                'name': name,
                'command': command
            }
            iter = store.iter_next(iter)
            i = i + 1

    def on_toggled(self, widget, path, data):
        treeview = data['treeview']
        store = treeview.get_model()
        iter = store.get_iter(path)
        (enabled, name, command) = store.get(iter, CC_COL_ENABLED, CC_COL_NAME,
                                             CC_COL_COMMAND)
        store.set_value(iter, CC_COL_ENABLED, not enabled)

    def on_selection_changed(self, selection, data=None):
        treeview = selection.get_tree_view()
        (model, iter) = selection.get_selected()
        data['button_top'].set_sensitive(iter is not None)
        data['button_up'].set_sensitive(iter is not None)
        data['button_down'].set_sensitive(iter is not None)
        data['button_last'].set_sensitive(iter is not None)
        data['button_edit'].set_sensitive(iter is not None)
        data['button_delete'].set_sensitive(iter is not None)

    def _create_command_dialog(self,
                               enabled_var=False,
                               name_var="",
                               command_var=""):
        dialog = Gtk.Dialog(_("New Command"), None, Gtk.DialogFlags.MODAL,
                            (_("_Cancel"), Gtk.ResponseType.REJECT, _("_OK"),
                             Gtk.ResponseType.ACCEPT))
        table = Gtk.Table(3, 2)

        label = Gtk.Label(label=_("Enabled:"))
        table.attach(label, 0, 1, 0, 1)
        enabled = Gtk.CheckButton()
        enabled.set_active(enabled_var)
        table.attach(enabled, 1, 2, 0, 1)

        label = Gtk.Label(label=_("Name:"))
        table.attach(label, 0, 1, 1, 2)
        name = Gtk.Entry()
        name.set_text(name_var)
        table.attach(name, 1, 2, 1, 2)

        label = Gtk.Label(label=_("Command:"))
        table.attach(label, 0, 1, 2, 3)
        command = Gtk.Entry()
        command.set_text(command_var)
        table.attach(command, 1, 2, 2, 3)

        dialog.vbox.pack_start(table, True, True, 0)
        dialog.show_all()
        return (dialog, enabled, name, command)

    def on_new(self, button, data):
        (dialog, enabled, name, command) = self._create_command_dialog()
        res = dialog.run()
        item = {}
        if res == Gtk.ResponseType.ACCEPT:
            item['enabled'] = enabled.get_active()
            item['name'] = name.get_text()
            item['command'] = command.get_text()
            if item['name'] == '' or item['command'] == '':
                err = Gtk.MessageDialog(
                    dialog, Gtk.DialogFlags.MODAL, Gtk.MessageType.ERROR,
                    Gtk.ButtonsType.CLOSE,
                    _("You need to define a name and command"))
                err.run()
                err.destroy()
            else:
                # we have a new command
                store = data['treeview'].get_model()
                iter = store.get_iter_first()
                name_exist = False
                while iter != None:
                    if store.get_value(iter, CC_COL_NAME) == item['name']:
                        name_exist = True
                        break
                    iter = store.iter_next(iter)
                if not name_exist:
                    store.append(
                        (item['enabled'], item['name'], item['command']))
                else:
                    gerr(_("Name *%s* already exist") % item['name'])
        dialog.destroy()

    def on_goto_top(self, button, data):
        treeview = data['treeview']
        selection = treeview.get_selection()
        (store, iter) = selection.get_selected()

        if not iter:
            return
        firstiter = store.get_iter_first()
        store.move_before(iter, firstiter)

    def on_go_up(self, button, data):
        treeview = data['treeview']
        selection = treeview.get_selection()
        (store, iter) = selection.get_selected()

        if not iter:
            return

        tmpiter = store.get_iter_first()

        if (store.get_path(tmpiter) == store.get_path(iter)):
            return

        while tmpiter:
            next = store.iter_next(tmpiter)
            if (store.get_path(next) == store.get_path(iter)):
                store.swap(iter, tmpiter)
                break
            tmpiter = next

    def on_go_down(self, button, data):
        treeview = data['treeview']
        selection = treeview.get_selection()
        (store, iter) = selection.get_selected()

        if not iter:
            return
        next = store.iter_next(iter)
        if next:
            store.swap(iter, next)

    def on_goto_last(self, button, data):
        treeview = data['treeview']
        selection = treeview.get_selection()
        (store, iter) = selection.get_selected()

        if not iter:
            return
        lastiter = iter
        tmpiter = store.get_iter_first()
        while tmpiter:
            lastiter = tmpiter
            tmpiter = store.iter_next(tmpiter)

        store.move_after(iter, lastiter)

    def on_delete(self, button, data):
        treeview = data['treeview']
        selection = treeview.get_selection()
        (store, iter) = selection.get_selected()
        if iter:
            store.remove(iter)

        return

    def on_edit(self, button, data):
        treeview = data['treeview']
        selection = treeview.get_selection()
        (store, iter) = selection.get_selected()

        if not iter:
            return

        (dialog, enabled, name, command) = self._create_command_dialog(
            enabled_var=store.get_value(iter, CC_COL_ENABLED),
            name_var=store.get_value(iter, CC_COL_NAME),
            command_var=store.get_value(iter, CC_COL_COMMAND))
        res = dialog.run()
        item = {}
        if res == Gtk.ResponseType.ACCEPT:
            item['enabled'] = enabled.get_active()
            item['name'] = name.get_text()
            item['command'] = command.get_text()
            if item['name'] == '' or item['command'] == '':
                err = Gtk.MessageDialog(
                    dialog, Gtk.DialogFlags.MODAL, Gtk.MessageType.ERROR,
                    Gtk.ButtonsType.CLOSE,
                    _("You need to define a name and command"))
                err.run()
                err.destroy()
            else:
                tmpiter = store.get_iter_first()
                name_exist = False
                while tmpiter != None:
                    if store.get_path(tmpiter) != store.get_path(
                            iter) and store.get_value(
                                tmpiter, CC_COL_NAME) == item['name']:
                        name_exist = True
                        break
                    tmpiter = store.iter_next(tmpiter)
                if not name_exist:
                    store.set(iter, CC_COL_ENABLED, item['enabled'],
                              CC_COL_NAME, item['name'], CC_COL_COMMAND,
                              item['command'])
                else:
                    gerr(_("Name *%s* already exist") % item['name'])

        dialog.destroy()
예제 #8
0
    def load(self):
        """Load configuration data from our various sources"""
        if self.loaded is True:
            dbg('ConfigBase::load: config already loaded')
            return

        if self.command_line_options:
            if not self.command_line_options.config:
                self.command_line_options.config = os.path.join(
                    get_config_dir(), 'config')
            filename = self.command_line_options.config
        else:
            filename = os.path.join(get_config_dir(), 'config')

        dbg('looking for config file: %s' % filename)
        try:
            configfile = open(filename, 'r')
        except Exception as ex:
            if not self.whined:
                err('ConfigBase::load: Unable to open %s (%s)' %
                    (filename, ex))
                self.whined = True
            return
        # If we have successfully loaded a config, allow future whining
        self.whined = False

        try:
            configspec = self.defaults_to_configspec()
            parser = ConfigObj(configfile, configspec=configspec)
            validator = Validator()
            result = parser.validate(validator, preserve_errors=True)
        except Exception as ex:
            err('Unable to load configuration: %s' % ex)
            return

        if result != True:
            err('ConfigBase::load: config format is not valid')
            for (section_list, key, _other) in flatten_errors(parser, result):
                if key is not None:
                    err('[%s]: %s is invalid' % (','.join(section_list), key))
                else:
                    err('[%s] missing' % ','.join(section_list))
        else:
            dbg('config validated successfully')

        for section_name in self.sections:
            dbg('ConfigBase::load: Processing section: %s' % section_name)
            section = getattr(self, section_name)
            if section_name == 'profiles':
                for profile in parser[section_name]:
                    dbg('ConfigBase::load: Processing profile: %s' % profile)
                    if not section.has_key(section_name):
                        # FIXME: Should this be outside the loop?
                        section[profile] = copy(
                            DEFAULTS['profiles']['default'])
                    section[profile].update(parser[section_name][profile])
            elif section_name == 'plugins':
                if not parser.has_key(section_name):
                    continue
                for part in parser[section_name]:
                    dbg('ConfigBase::load: Processing %s: %s' %
                        (section_name, part))
                    section[part] = parser[section_name][part]
            elif section_name == 'layouts':
                for layout in parser[section_name]:
                    dbg('ConfigBase::load: Processing %s: %s' %
                        (section_name, layout))
                    if layout == 'default' and \
                       parser[section_name][layout] == {}:
                        continue
                    section[layout] = parser[section_name][layout]
            elif section_name == 'keybindings':
                if not parser.has_key(section_name):
                    continue
                for part in parser[section_name]:
                    dbg('ConfigBase::load: Processing %s: %s' %
                        (section_name, part))
                    if parser[section_name][part] == 'None':
                        section[part] = None
                    else:
                        section[part] = parser[section_name][part]
            else:
                try:
                    section.update(parser[section_name])
                except KeyError as ex:
                    dbg('ConfigBase::load: skipping missing section %s' %
                        section_name)

        self.loaded = True
예제 #9
0
class SSHMenu(plugin.MenuItem):
    """SSH Menu"""
    capabilities = ['terminal_menu']
    cmd_list = []
    conf_file = os.path.join(get_config_dir(), "ssh_menu")

    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 callback(self, menuitems, menu, terminal):
        """Add our menu items to the menu"""
        item = gtk.MenuItem(_('SSH Menu'))
        item.connect("activate", self.menu, terminal)
        menuitems.append(item)

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

    #  menuitem = gtk.ImageMenuItem(gtk.STOCK_PREFERENCES)
    #  menuitem.connect("activate", self.configure)
    #  submenu.append(menuitem)

    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

    def _save_order(self, selection, data):
        print "todo!"

    def _execute(self, treeview, path, view_column, data):
        (model, iter) = data['selection'].get_selected()
        command = model.get_value(iter, 1)
        if command[len(command) - 1] != '\n':
            command = command + '\n'
        data['terminal'].vte.feed_child(command)

    def menu(self, widget, terminal, data=None):
        ui = {}

        window = gtk.Window()
        scroll = gtk.ScrolledWindow(None, None)
        scroll.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_ALWAYS)
        #scroll.set_border_width(1)

        window.set_title("SSH Menu")
        window.move(1, 100)
        window.resize(200, 500)
        window.set_resizable(True)
        #window. set_decorated(False)
        # Create a new button
        buttonsbox = gtk.HBox(False, 0)
        box1 = gtk.VBox(False, 0)

        button = gtk.Button("Close", gtk.STOCK_CLOSE)
        button.connect_object("clicked", gtk.Widget.destroy, window)

        buttonPreferences = gtk.Button("Close", gtk.STOCK_PREFERENCES)
        buttonPreferences.connect("clicked", self.configure)

        buttonsbox.pack_start(button, True, False, 0)
        buttonsbox.pack_end(buttonPreferences, True, False, 0)
        box1.pack_start(buttonsbox, False, False, 0)

        store = gtk.TreeStore(str, str)
        rabbit = store.append(None, ["Main", "men"])
        for command in self.cmd_list:
            store.append(rabbit, [command['name'], command['command']])

        treeview = gtk.TreeView(store)
        selection = treeview.get_selection()
        selection.set_mode(gtk.SELECTION_SINGLE)

        selection.connect("changed", self._save_order, {
            'terminal': terminal,
            'selection': selection
        })
        treeview.connect("row-activated", self._execute, {
            'terminal': terminal,
            'selection': selection
        })
        ui['treeview'] = treeview

        renderer = gtk.CellRendererText()
        column = gtk.TreeViewColumn("Hosts", renderer, text=CC_COL_NAME)

        treeview.append_column(column)

        treeview.set_reorderable(True)
        treeview.set_enable_search(True)

        hbox = gtk.HBox()
        hbox.pack_start(treeview)

        outbox = gtk.VBox(False, 0)

        inbox = gtk.VBox(False, 0)
        inbox.pack_start(scroll, True, True, 5)
        inbox.pack_start(box1, False, False, 8)

        scroll.add_with_viewport(hbox)
        scroll.show()
        outbox.pack_start(inbox)
        window.add(outbox)
        window.show_all()

        return

    def configure(self, widget, data=None):
        ui = {}
        window = gtk.Dialog(_("SSH Menu Configuration"), None,
                            gtk.DIALOG_MODAL,
                            (gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT,
                             gtk.STOCK_OK, gtk.RESPONSE_ACCEPT))
        store = gtk.ListStore(str, str)

        for command in self.cmd_list:
            store.append([command['name'], command['command']])

        treeview = gtk.TreeView(store)
        #treeview.connect("cursor-changed", self.on_cursor_changed, ui)
        selection = treeview.get_selection()
        selection.set_mode(gtk.SELECTION_SINGLE)
        selection.connect("changed", self.on_selection_changed, ui)
        ui['treeview'] = treeview

        renderer = gtk.CellRendererText()
        column = gtk.TreeViewColumn("Name", renderer, text=CC_COL_NAME)
        treeview.append_column(column)

        renderer = gtk.CellRendererText()
        column = gtk.TreeViewColumn("Command", renderer, text=CC_COL_COMMAND)
        treeview.append_column(column)

        hbox = gtk.HBox()
        hbox.pack_start(treeview)
        window.vbox.pack_start(hbox)

        button_box = gtk.VBox()

        button = gtk.Button(stock=gtk.STOCK_GOTO_TOP)
        button_box.pack_start(button, False, True)
        button.connect("clicked", self.on_goto_top, ui)
        button.set_sensitive(False)
        ui['button_top'] = button

        button = gtk.Button(stock=gtk.STOCK_GO_UP)
        button_box.pack_start(button, False, True)
        button.connect("clicked", self.on_go_up, ui)
        button.set_sensitive(False)
        ui['button_up'] = button

        button = gtk.Button(stock=gtk.STOCK_GO_DOWN)
        button_box.pack_start(button, False, True)
        button.connect("clicked", self.on_go_down, ui)
        button.set_sensitive(False)
        ui['button_down'] = button

        button = gtk.Button(stock=gtk.STOCK_GOTO_LAST)
        button_box.pack_start(button, False, True)
        button.connect("clicked", self.on_goto_last, ui)
        button.set_sensitive(False)
        ui['button_last'] = button

        button = gtk.Button(stock=gtk.STOCK_NEW)
        button_box.pack_start(button, False, True)
        button.connect("clicked", self.on_new, ui)
        ui['button_new'] = button

        button = gtk.Button(stock=gtk.STOCK_EDIT)
        button_box.pack_start(button, False, True)
        button.set_sensitive(False)
        button.connect("clicked", self.on_edit, ui)
        ui['button_edit'] = button

        button = gtk.Button(stock=gtk.STOCK_DELETE)
        button_box.pack_start(button, False, True)
        button.connect("clicked", self.on_delete, ui)
        button.set_sensitive(False)
        ui['button_delete'] = button

        hbox.pack_start(button_box)
        window.show_all()
        res = window.run()
        if res == gtk.RESPONSE_ACCEPT:
            #we save the config
            iter = store.get_iter_first()
            self.cmd_list = []
            while iter:
                (name, command) = store.get(iter, CC_COL_NAME, CC_COL_COMMAND)
                self.cmd_list.append({'name': name, 'command': command})
                iter = store.iter_next(iter)
            self._save_config()

        window.destroy()
        return

    def on_selection_changed(self, selection, data=None):
        treeview = selection.get_tree_view()
        (model, iter) = selection.get_selected()
        data['button_top'].set_sensitive(iter is not None)
        data['button_up'].set_sensitive(iter is not None)
        data['button_down'].set_sensitive(iter is not None)
        data['button_last'].set_sensitive(iter is not None)
        data['button_edit'].set_sensitive(iter is not None)
        data['button_delete'].set_sensitive(iter is not None)

    def _create_command_dialog(self, name_var="", command_var=""):
        dialog = gtk.Dialog(_("New Command"), None, gtk.DIALOG_MODAL,
                            (gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT,
                             gtk.STOCK_OK, gtk.RESPONSE_ACCEPT))
        table = gtk.Table(3, 2)

        label = gtk.Label(_("Name:"))
        table.attach(label, 0, 1, 1, 2)
        name = gtk.Entry()
        name.set_text(name_var)
        table.attach(name, 1, 2, 1, 2)

        label = gtk.Label(_("Command:"))
        table.attach(label, 0, 1, 2, 3)
        command = gtk.Entry()
        command.set_text(command_var)
        table.attach(command, 1, 2, 2, 3)

        dialog.vbox.pack_start(table)
        dialog.show_all()
        return (dialog, name, command)

    def _error(self, msg):
        err = gtk.MessageDialog(dialog, gtk.DIALOG_MODAL, gtk.MESSAGE_ERROR,
                                gtk.BUTTONS_CLOSE, msg)
        err.run()
        err.destroy()

    def on_new(self, button, data):
        (dialog, name, command) = self._create_command_dialog()
        res = dialog.run()
        item = {}
        if res == gtk.RESPONSE_ACCEPT:
            item['name'] = name.get_text()
            item['command'] = command.get_text()
            if item['name'] == '' or item['command'] == '':
                err = gtk.MessageDialog(
                    dialog, gtk.DIALOG_MODAL, gtk.MESSAGE_ERROR,
                    gtk.BUTTONS_CLOSE,
                    _("You need to define a name and command"))
                err.run()
                err.destroy()
            else:
                # we have a new command
                store = data['treeview'].get_model()
                iter = store.get_iter_first()
                name_exist = False
                while iter != None:
                    if store.get_value(iter, CC_COL_NAME) == item['name']:
                        name_exist = True
                        break
                    iter = store.iter_next(iter)
                if not name_exist:
                    store.append((item['name'], item['command']))
                else:
                    self._err(_("Name *%s* already exist") % item['name'])
        dialog.destroy()

    def on_goto_top(self, button, data):
        treeview = data['treeview']
        selection = treeview.get_selection()
        (store, iter) = selection.get_selected()

        if not iter:
            return
        firstiter = store.get_iter_first()
        store.move_before(iter, firstiter)

    def on_go_up(self, button, data):
        treeview = data['treeview']
        selection = treeview.get_selection()
        (store, iter) = selection.get_selected()

        if not iter:
            return

        tmpiter = store.get_iter_first()

        if (store.get_path(tmpiter) == store.get_path(iter)):
            return

        while tmpiter:
            next = store.iter_next(tmpiter)
            if (store.get_path(next) == store.get_path(iter)):
                store.swap(iter, tmpiter)
                break
            tmpiter = next

    def on_go_down(self, button, data):
        treeview = data['treeview']
        selection = treeview.get_selection()
        (store, iter) = selection.get_selected()

        if not iter:
            return
        next = store.iter_next(iter)
        if next:
            store.swap(iter, next)

    def on_goto_last(self, button, data):
        treeview = data['treeview']
        selection = treeview.get_selection()
        (store, iter) = selection.get_selected()

        if not iter:
            return
        lastiter = iter
        tmpiter = store.get_iter_first()
        while tmpiter:
            lastiter = tmpiter
            tmpiter = store.iter_next(tmpiter)

        store.move_after(iter, lastiter)

    def on_delete(self, button, data):
        treeview = data['treeview']
        selection = treeview.get_selection()
        (store, iter) = selection.get_selected()
        if iter:
            store.remove(iter)

        return

    def on_edit(self, button, data):
        treeview = data['treeview']
        selection = treeview.get_selection()
        (store, iter) = selection.get_selected()

        if not iter:
            return

        (dialog, name, command) = self._create_command_dialog(
            name_var=store.get_value(iter, CC_COL_NAME),
            command_var=store.get_value(iter, CC_COL_COMMAND))
        res = dialog.run()
        item = {}
        if res == gtk.RESPONSE_ACCEPT:
            item['name'] = name.get_text()
            item['command'] = command.get_text()
            if item['name'] == '' or item['command'] == '':
                err = gtk.MessageDialog(
                    dialog, gtk.DIALOG_MODAL, gtk.MESSAGE_ERROR,
                    gtk.BUTTONS_CLOSE,
                    _("You need to define a name and command"))
                err.run()
                err.destroy()
            else:
                tmpiter = store.get_iter_first()
                name_exist = False
                while tmpiter != None:
                    if store.get_path(tmpiter) != store.get_path(
                            iter) and store.get_value(
                                tmpiter, CC_COL_NAME) == item['name']:
                        name_exist = True
                        break
                    tmpiter = store.iter_next(tmpiter)
                if not name_exist:
                    store.set(iter, CC_COL_NAME, item['name'], CC_COL_COMMAND,
                              item['command'])
                else:
                    self._err(_("Name *%s* already exist") % item['name'])

        dialog.destroy()
예제 #10
0
class CustomCommandsMenu(plugin.MenuItem):
    """Add custom commands to the terminal menu"""
    capabilities = ['terminal_menu']
    cmd_list = []
    conf_file = os.path.join(get_config_dir(), "custom_commands")

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

    def callback(self, menuitems, menu, terminal):
        """Add our menu items to the menu"""
        item = gtk.MenuItem(_('Custom Commands'))
        menuitems.append(item)

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

        menuitem = gtk.ImageMenuItem(gtk.STOCK_PREFERENCES)
        menuitem.connect("activate", self.configure)
        submenu.append(menuitem)

        menuitem = gtk.SeparatorMenuItem()
        submenu.append(menuitem)

        theme = gtk.IconTheme()
        for command in self.cmd_list:
            if not command['enabled']:
                continue
            exe = command['command'].split(' ')[0]
            iconinfo = theme.choose_icon([exe], gtk.ICON_SIZE_MENU,
                                         gtk.ICON_LOOKUP_USE_BUILTIN)
            if iconinfo:
                image = gtk.Image()
                image.set_from_icon_name(exe, gtk.ICON_SIZE_MENU)
                menuitem = gtk.ImageMenuItem(command['name'])
                menuitem.set_image(image)
            else:
                menuitem = gtk.MenuItem(command["name"])
            menuitem.connect("activate", self._execute, {
                'terminal': terminal,
                'command': command['command']
            })
            submenu.append(menuitem)

    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

    def _execute(self, widget, data):
        command = data['command']
        if command[len(command) - 1] != '\n':
            command = command + '\n'
        data['terminal'].vte.feed_child(command)

    def configure(self, widget, data=None):
        ui = {}
        dbox = gtk.Dialog(_("Custom Commands Configuration"), None,
                          gtk.DIALOG_MODAL,
                          (gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT, gtk.STOCK_OK,
                           gtk.RESPONSE_ACCEPT))
        store = gtk.ListStore(bool, str, str)

        for command in self.cmd_list:
            store.append(
                [command['enabled'], command['name'], command['command']])

        treeview = gtk.TreeView(store)
        #treeview.connect("cursor-changed", self.on_cursor_changed, ui)
        selection = treeview.get_selection()
        selection.set_mode(gtk.SELECTION_SINGLE)
        selection.connect("changed", self.on_selection_changed, ui)
        ui['treeview'] = treeview

        renderer = gtk.CellRendererToggle()
        renderer.connect('toggled', self.on_toggled, ui)
        column = gtk.TreeViewColumn("Enabled", renderer, active=CC_COL_ENABLED)
        treeview.append_column(column)

        renderer = gtk.CellRendererText()
        column = gtk.TreeViewColumn("Name", renderer, text=CC_COL_NAME)
        treeview.append_column(column)

        renderer = gtk.CellRendererText()
        column = gtk.TreeViewColumn("Command", renderer, text=CC_COL_COMMAND)
        treeview.append_column(column)

        hbox = gtk.HBox()
        hbox.pack_start(treeview)
        dbox.vbox.pack_start(hbox)

        button_box = gtk.VBox()

        button = gtk.Button(stock=gtk.STOCK_GOTO_TOP)
        button_box.pack_start(button, False, True)
        button.connect("clicked", self.on_goto_top, ui)
        button.set_sensitive(False)
        ui['button_top'] = button

        button = gtk.Button(stock=gtk.STOCK_GO_UP)
        button_box.pack_start(button, False, True)
        button.connect("clicked", self.on_go_up, ui)
        button.set_sensitive(False)
        ui['button_up'] = button

        button = gtk.Button(stock=gtk.STOCK_GO_DOWN)
        button_box.pack_start(button, False, True)
        button.connect("clicked", self.on_go_down, ui)
        button.set_sensitive(False)
        ui['button_down'] = button

        button = gtk.Button(stock=gtk.STOCK_GOTO_LAST)
        button_box.pack_start(button, False, True)
        button.connect("clicked", self.on_goto_last, ui)
        button.set_sensitive(False)
        ui['button_last'] = button

        button = gtk.Button(stock=gtk.STOCK_NEW)
        button_box.pack_start(button, False, True)
        button.connect("clicked", self.on_new, ui)
        ui['button_new'] = button

        button = gtk.Button(stock=gtk.STOCK_EDIT)
        button_box.pack_start(button, False, True)
        button.set_sensitive(False)
        button.connect("clicked", self.on_edit, ui)
        ui['button_edit'] = button

        button = gtk.Button(stock=gtk.STOCK_DELETE)
        button_box.pack_start(button, False, True)
        button.connect("clicked", self.on_delete, ui)
        button.set_sensitive(False)
        ui['button_delete'] = button

        hbox.pack_start(button_box)
        dbox.show_all()
        res = dbox.run()
        if res == gtk.RESPONSE_ACCEPT:
            #we save the config
            iter = store.get_iter_first()
            self.cmd_list = []
            while iter:
                (enabled, name, command) = store.get(iter, CC_COL_ENABLED,
                                                     CC_COL_NAME,
                                                     CC_COL_COMMAND)
                self.cmd_list.append({
                    'enabled': enabled,
                    'name': name,
                    'command': command
                })
                iter = store.iter_next(iter)
            self._save_config()

        dbox.destroy()
        return

    def on_toggled(self, widget, path, data):
        treeview = data['treeview']
        store = treeview.get_model()
        iter = store.get_iter(path)
        (enabled, name, command) = store.get(iter, CC_COL_ENABLED, CC_COL_NAME,
                                             CC_COL_COMMAND)
        store.set_value(iter, CC_COL_ENABLED, not enabled)
        for cmd in self.cmd_list:
            if cmd['name'] == name:
                cmd['enabled'] = not enabled
                break

    def on_selection_changed(self, selection, data=None):
        treeview = selection.get_tree_view()
        (model, iter) = selection.get_selected()
        data['button_top'].set_sensitive(iter is not None)
        data['button_up'].set_sensitive(iter is not None)
        data['button_down'].set_sensitive(iter is not None)
        data['button_last'].set_sensitive(iter is not None)
        data['button_edit'].set_sensitive(iter is not None)
        data['button_delete'].set_sensitive(iter is not None)

    def _create_command_dialog(self,
                               enabled_var=False,
                               name_var="",
                               command_var=""):
        dialog = gtk.Dialog(_("New Command"), None, gtk.DIALOG_MODAL,
                            (gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT,
                             gtk.STOCK_OK, gtk.RESPONSE_ACCEPT))
        table = gtk.Table(3, 2)

        label = gtk.Label(_("Enabled:"))
        table.attach(label, 0, 1, 0, 1)
        enabled = gtk.CheckButton()
        enabled.set_active(enabled_var)
        table.attach(enabled, 1, 2, 0, 1)

        label = gtk.Label(_("Name:"))
        table.attach(label, 0, 1, 1, 2)
        name = gtk.Entry()
        name.set_text(name_var)
        table.attach(name, 1, 2, 1, 2)

        label = gtk.Label(_("Command:"))
        table.attach(label, 0, 1, 2, 3)
        command = gtk.Entry()
        command.set_text(command_var)
        table.attach(command, 1, 2, 2, 3)

        dialog.vbox.pack_start(table)
        dialog.show_all()
        return (dialog, enabled, name, command)

    def _error(self, msg):
        err = gtk.MessageDialog(dialog, gtk.DIALOG_MODAL, gtk.MESSAGE_ERROR,
                                gtk.BUTTONS_CLOSE, msg)
        err.run()
        err.destroy()

    def on_new(self, button, data):
        (dialog, enabled, name, command) = self._create_command_dialog()
        res = dialog.run()
        item = {}
        if res == gtk.RESPONSE_ACCEPT:
            item['enabled'] = enabled.get_active()
            item['name'] = name.get_text()
            item['command'] = command.get_text()
            if item['name'] == '' or item['command'] == '':
                err = gtk.MessageDialog(
                    dialog, gtk.DIALOG_MODAL, gtk.MESSAGE_ERROR,
                    gtk.BUTTONS_CLOSE,
                    _("You need to define a name and command"))
                err.run()
                err.destroy()
            else:
                # we have a new command
                store = data['treeview'].get_model()
                iter = store.get_iter_first()
                name_exist = False
                while iter != None:
                    if store.get_value(iter, CC_COL_NAME) == item['name']:
                        name_exist = True
                        break
                    iter = store.iter_next(iter)
                if not name_exist:
                    store.append(
                        (item['enabled'], item['name'], item['command']))
                else:
                    self._err(_("Name *%s* already exist") % item['name'])
        dialog.destroy()

    def on_goto_top(self, button, data):
        treeview = data['treeview']
        selection = treeview.get_selection()
        (store, iter) = selection.get_selected()

        if not iter:
            return
        firstiter = store.get_iter_first()
        store.move_before(iter, firstiter)

    def on_go_up(self, button, data):
        treeview = data['treeview']
        selection = treeview.get_selection()
        (store, iter) = selection.get_selected()

        if not iter:
            return

        tmpiter = store.get_iter_first()

        if (store.get_path(tmpiter) == store.get_path(iter)):
            return

        while tmpiter:
            next = store.iter_next(tmpiter)
            if (store.get_path(next) == store.get_path(iter)):
                store.swap(iter, tmpiter)
                break
            tmpiter = next

    def on_go_down(self, button, data):
        treeview = data['treeview']
        selection = treeview.get_selection()
        (store, iter) = selection.get_selected()

        if not iter:
            return
        next = store.iter_next(iter)
        if next:
            store.swap(iter, next)

    def on_goto_last(self, button, data):
        treeview = data['treeview']
        selection = treeview.get_selection()
        (store, iter) = selection.get_selected()

        if not iter:
            return
        lastiter = iter
        tmpiter = store.get_iter_first()
        while tmpiter:
            lastiter = tmpiter
            tmpiter = store.iter_next(tmpiter)

        store.move_after(iter, lastiter)

    def on_delete(self, button, data):
        treeview = data['treeview']
        selection = treeview.get_selection()
        (store, iter) = selection.get_selected()
        if iter:
            store.remove(iter)

        return

    def on_edit(self, button, data):
        treeview = data['treeview']
        selection = treeview.get_selection()
        (store, iter) = selection.get_selected()

        if not iter:
            return

        (dialog, enabled, name, command) = self._create_command_dialog(
            enabled_var=store.get_value(iter, CC_COL_ENABLED),
            name_var=store.get_value(iter, CC_COL_NAME),
            command_var=store.get_value(iter, CC_COL_COMMAND))
        res = dialog.run()
        item = {}
        if res == gtk.RESPONSE_ACCEPT:
            item['enabled'] = enabled.get_active()
            item['name'] = name.get_text()
            item['command'] = command.get_text()
            if item['name'] == '' or item['command'] == '':
                err = gtk.MessageDialog(
                    dialog, gtk.DIALOG_MODAL, gtk.MESSAGE_ERROR,
                    gtk.BUTTONS_CLOSE,
                    _("You need to define a name and command"))
                err.run()
                err.destroy()
            else:
                tmpiter = store.get_iter_first()
                name_exist = False
                while tmpiter != None:
                    if store.get_path(tmpiter) != store.get_path(
                            iter) and store.get_value(
                                tmpiter, CC_COL_NAME) == item['name']:
                        name_exist = True
                        break
                    tmpiter = store.iter_next(tmpiter)
                if not name_exist:
                    store.set(iter, CC_COL_ENABLED, item['enabled'],
                              CC_COL_NAME, item['name'], CC_COL_COMMAND,
                              item['command'])
                else:
                    self._err(_("Name *%s* already exist") % item['name'])

        dialog.destroy()
예제 #11
0
 def setConfigDir(self):
     if self.configDir is None:
         configDir = join(get_config_dir(), LAYOUTMANAGER_NAME) 
         if not exists(configDir):
             makedirs(configDir)            
         self.configDir = configDir
예제 #12
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()
예제 #13
0
 def setConfigDir(self):
     if self.configDir is None:
         configDir = join(get_config_dir(), LAYOUTMANAGER_NAME)
         if not exists(configDir):
             makedirs(configDir)
         self.configDir = configDir
예제 #14
0
class RunCmdOnMatchMenu(plugin.MenuItem):
    """Add custom match/commands preference setting to the terminal menu"""
    capabilities = ['terminal_menu']
    cmd_list = {}
    conf_file = os.path.join(get_config_dir(), "run_cmd_on_match")

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

    def callback(self, menuitems, menu, terminal):
        """Add our menu items to the menu"""
        submenus = {}
        item = Gtk.MenuItem.new_with_mnemonic(_('_Run command on matches'))
        menuitems.append(item)

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

        menuitem = Gtk.MenuItem.new_with_mnemonic(_('_Preferences'))
        menuitem.connect("activate", self.configure)
        submenu.append(menuitem)

        menuitem = Gtk.SeparatorMenuItem()
        submenu.append(menuitem)

        theme = Gtk.IconTheme.get_default()

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

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

    def _execute(self, widget, data):
        command = data['command']
        if command[-1] != '\n':
            command = command + '\n'
        for terminal in data['terminals']:
            terminal.vte.feed_child(command.encode())

    def configure(self, widget, data=None):
        ui = {}
        dbox = Gtk.Dialog(_("Run command on match Configuration"), None,
                          Gtk.DialogFlags.MODAL,
                          (_("_Cancel"), Gtk.ResponseType.REJECT, _("_OK"),
                           Gtk.ResponseType.ACCEPT))
        dbox.set_transient_for(widget.get_toplevel())

        icon_theme = Gtk.IconTheme.get_default()
        if icon_theme.lookup_icon('terminator-run-cmd-on-match', 48, 0):
            dbox.set_icon_name('terminator-run-cmd-on-match')
        else:
            dbg('Unable to load Terminator run-cmd-on-match icon')
            icon = dbox.render_icon(Gtk.STOCK_DIALOG_INFO, Gtk.IconSize.BUTTON)
            dbox.set_icon(icon)

        store = Gtk.ListStore(bool, str, str)

        for command in [
                self.cmd_list[key] for key in sorted(self.cmd_list.keys())
        ]:
            store.append(
                [command['enabled'], command['regexp'], command['command']])

        treeview = Gtk.TreeView(store)
        #treeview.connect("cursor-changed", self.on_cursor_changed, ui)
        selection = treeview.get_selection()
        selection.set_mode(Gtk.SelectionMode.SINGLE)
        selection.connect("changed", self.on_selection_changed, ui)
        ui['treeview'] = treeview

        renderer = Gtk.CellRendererToggle()
        renderer.connect('toggled', self.on_toggled, ui)
        column = Gtk.TreeViewColumn(_("Enabled"),
                                    renderer,
                                    active=CC_COL_ENABLED)
        treeview.append_column(column)

        renderer = Gtk.CellRendererText()
        column = Gtk.TreeViewColumn(_("regexp"), renderer, text=CC_COL_REGEXP)
        treeview.append_column(column)

        renderer = Gtk.CellRendererText()
        column = Gtk.TreeViewColumn(_("Command"),
                                    renderer,
                                    text=CC_COL_COMMAND)
        treeview.append_column(column)

        scroll_window = Gtk.ScrolledWindow()
        scroll_window.set_size_request(500, 250)
        scroll_window.set_policy(Gtk.PolicyType.AUTOMATIC,
                                 Gtk.PolicyType.AUTOMATIC)
        scroll_window.add_with_viewport(treeview)

        hbox = Gtk.HBox()
        hbox.pack_start(scroll_window, True, True, 0)
        dbox.vbox.pack_start(hbox, True, True, 0)

        button_box = Gtk.VBox()

        button = Gtk.Button(_("Top"))
        button_box.pack_start(button, False, True, 0)
        button.connect("clicked", self.on_goto_top, ui)
        button.set_sensitive(False)
        ui['button_top'] = button

        button = Gtk.Button(_("Up"))
        button_box.pack_start(button, False, True, 0)
        button.connect("clicked", self.on_go_up, ui)
        button.set_sensitive(False)
        ui['button_up'] = button

        button = Gtk.Button(_("Down"))
        button_box.pack_start(button, False, True, 0)
        button.connect("clicked", self.on_go_down, ui)
        button.set_sensitive(False)
        ui['button_down'] = button

        button = Gtk.Button(_("Last"))
        button_box.pack_start(button, False, True, 0)
        button.connect("clicked", self.on_goto_last, ui)
        button.set_sensitive(False)
        ui['button_last'] = button

        button = Gtk.Button(_("New"))
        button_box.pack_start(button, False, True, 0)
        button.connect("clicked", self.on_new, ui)
        ui['button_new'] = button

        button = Gtk.Button(_("Edit"))
        button_box.pack_start(button, False, True, 0)
        button.set_sensitive(False)
        button.connect("clicked", self.on_edit, ui)
        ui['button_edit'] = button

        button = Gtk.Button(_("Delete"))
        button_box.pack_start(button, False, True, 0)
        button.connect("clicked", self.on_delete, ui)
        button.set_sensitive(False)
        ui['button_delete'] = button

        hbox.pack_start(button_box, False, True, 0)
        self.dbox = dbox
        dbox.show_all()
        res = dbox.run()
        if res == Gtk.ResponseType.ACCEPT:
            self.update_cmd_list(store)
            self._save_config()
        del (self.dbox)
        dbox.destroy()
        return

    def update_cmd_list(self, store):
        iter = store.get_iter_first()
        self.cmd_list = {}
        i = 0
        while iter:
            (enabled, regexp, command) = store.get(iter, CC_COL_ENABLED,
                                                   CC_COL_REGEXP,
                                                   CC_COL_COMMAND)
            self.cmd_list[i] = {
                'enabled': enabled,
                'regexp': regexp,
                'command': command
            }
            iter = store.iter_next(iter)
            i = i + 1

    def on_toggled(self, widget, path, data):
        treeview = data['treeview']
        store = treeview.get_model()
        iter = store.get_iter(path)
        (enabled, regexp, command) = store.get(iter, CC_COL_ENABLED,
                                               CC_COL_REGEXP, CC_COL_COMMAND)
        store.set_value(iter, CC_COL_ENABLED, not enabled)

    def on_selection_changed(self, selection, data=None):
        treeview = selection.get_tree_view()
        (model, iter) = selection.get_selected()
        data['button_top'].set_sensitive(iter is not None)
        data['button_up'].set_sensitive(iter is not None)
        data['button_down'].set_sensitive(iter is not None)
        data['button_last'].set_sensitive(iter is not None)
        data['button_edit'].set_sensitive(iter is not None)
        data['button_delete'].set_sensitive(iter is not None)

    def _create_command_dialog(self,
                               enabled_var=False,
                               regexp_var="",
                               command_var=""):
        dialog = Gtk.Dialog(_("New Command"), None, Gtk.DialogFlags.MODAL,
                            (_("_Cancel"), Gtk.ResponseType.REJECT, _("_OK"),
                             Gtk.ResponseType.ACCEPT))
        dialog.set_transient_for(self.dbox)
        table = Gtk.Table(3, 2)

        label = Gtk.Label(label=_("Enabled:"))
        table.attach(label, 0, 1, 0, 1)
        enabled = Gtk.CheckButton()
        enabled.set_active(enabled_var)
        table.attach(enabled, 1, 2, 0, 1)

        label = Gtk.Label(label=_("regexp:"))
        table.attach(label, 0, 1, 1, 2)
        regexp = Gtk.Entry()
        regexp.set_text(regexp_var)
        table.attach(regexp, 1, 2, 1, 2)

        label = Gtk.Label(label=_("Command:"))
        table.attach(label, 0, 1, 2, 3)
        command = Gtk.Entry()
        command.set_text(command_var)
        table.attach(command, 1, 2, 2, 3)

        dialog.vbox.pack_start(table, True, True, 0)
        dialog.show_all()
        return (dialog, enabled, regexp, command)

    def on_new(self, button, data):
        (dialog, enabled, regexp, command) = self._create_command_dialog()
        res = dialog.run()
        item = {}
        if res == Gtk.ResponseType.ACCEPT:
            item['enabled'] = enabled.get_active()
            item['regexp'] = regexp.get_text()
            item['command'] = command.get_text()
            if item['regexp'] == '' or item['command'] == '':
                err = Gtk.MessageDialog(
                    dialog, Gtk.DialogFlags.MODAL, Gtk.MessageType.ERROR,
                    Gtk.ButtonsType.CLOSE,
                    _("You need to define a regexp and command"))
                err.run()
                err.destroy()
            else:
                # we have a new command
                store = data['treeview'].get_model()
                iter = store.get_iter_first()
                regexp_exist = False
                while iter != None:
                    if store.get_value(iter, CC_COL_REGEXP) == item['regexp']:
                        regexp_exist = True
                        break
                    iter = store.iter_next(iter)
                if not regexp_exist:
                    store.append(
                        (item['enabled'], item['regexp'], item['command']))
                else:
                    gerr(_("regexp *%s* already exist") % item['regexp'])
        dialog.destroy()

    def on_goto_top(self, button, data):
        treeview = data['treeview']
        selection = treeview.get_selection()
        (store, iter) = selection.get_selected()

        if not iter:
            return
        firstiter = store.get_iter_first()
        store.move_before(iter, firstiter)

    def on_go_up(self, button, data):
        treeview = data['treeview']
        selection = treeview.get_selection()
        (store, iter) = selection.get_selected()

        if not iter:
            return

        tmpiter = store.get_iter_first()

        if (store.get_path(tmpiter) == store.get_path(iter)):
            return

        while tmpiter:
            next = store.iter_next(tmpiter)
            if (store.get_path(next) == store.get_path(iter)):
                store.swap(iter, tmpiter)
                break
            tmpiter = next

    def on_go_down(self, button, data):
        treeview = data['treeview']
        selection = treeview.get_selection()
        (store, iter) = selection.get_selected()

        if not iter:
            return
        next = store.iter_next(iter)
        if next:
            store.swap(iter, next)

    def on_goto_last(self, button, data):
        treeview = data['treeview']
        selection = treeview.get_selection()
        (store, iter) = selection.get_selected()

        if not iter:
            return
        lastiter = iter
        tmpiter = store.get_iter_first()
        while tmpiter:
            lastiter = tmpiter
            tmpiter = store.iter_next(tmpiter)

        store.move_after(iter, lastiter)

    def on_delete(self, button, data):
        treeview = data['treeview']
        selection = treeview.get_selection()
        (store, iter) = selection.get_selected()
        if iter:
            store.remove(iter)

        return

    def on_edit(self, button, data):
        treeview = data['treeview']
        selection = treeview.get_selection()
        (store, iter) = selection.get_selected()

        if not iter:
            return

        (dialog, enabled, regexp, command) = self._create_command_dialog(
            enabled_var=store.get_value(iter, CC_COL_ENABLED),
            regexp_var=store.get_value(iter, CC_COL_REGEXP),
            command_var=store.get_value(iter, CC_COL_COMMAND))
        res = dialog.run()
        item = {}
        if res == Gtk.ResponseType.ACCEPT:
            item['enabled'] = enabled.get_active()
            item['regexp'] = regexp.get_text()
            item['command'] = command.get_text()
            if item['regexp'] == '' or item['command'] == '':
                err = Gtk.MessageDialog(
                    dialog, Gtk.DialogFlags.MODAL, Gtk.MessageType.ERROR,
                    Gtk.ButtonsType.CLOSE,
                    _("You need to define a regexp and a command"))
                err.run()
                err.destroy()
            else:
                tmpiter = store.get_iter_first()
                regexp_exist = False
                while tmpiter != None:
                    if store.get_path(tmpiter) != store.get_path(
                            iter) and store.get_value(
                                tmpiter, CC_COL_REGEXP) == item['regexp']:
                        regexp_exist = True
                        break
                    tmpiter = store.iter_next(tmpiter)
                if not regexp_exist:
                    store.set(iter, CC_COL_ENABLED, item['enabled'],
                              CC_COL_REGEXP, item['regexp'], CC_COL_COMMAND,
                              item['command'])
                else:
                    gerr(_("regexp *%s* already exist") % item['regexp'])

        dialog.destroy()