Ejemplo n.º 1
0
class TerminatorThemes(plugin.Plugin):

    capabilities = ['terminal_menu']
    config_base = ConfigBase()
    base_url = 'https://api.github.com/repos/EliverLara/terminator-themes/contents/themes.json'
    inherits_config_from = "default"

    def callback(self, menuitems, menu, terminal):
        """Add our item to the menu"""
        self.terminal = terminal
        item = Gtk.ImageMenuItem(Gtk.STOCK_FIND)
        item.connect('activate', self.configure)
        item.set_label("Themes")
        item.set_sensitive(True)
        menuitems.append(item)

    def configure(self, widget, data=None):
        ui = {}
        dbox = Gtk.Dialog(_("Terminator themes"), None, Gtk.DialogFlags.MODAL)

        headers = {"Accept": "application/vnd.github.v3.raw"}
        response = requests.get(self.base_url, headers=headers)

        if response.status_code != 200:
            gerr(_("Failed to get list of available themes"))
            return

        self.themes_from_repo = response.json()["themes"]
        self.profiles = self.terminal.config.list_profiles()

        main_container = Gtk.HBox(spacing=5)
        main_container.pack_start(self._create_themes_grid(ui), True, True,
                                  0)  #Left column
        main_container.pack_start(self._create_settings_grid(ui), True, True,
                                  0)  #Right column

        dbox.vbox.pack_start(main_container, True, True, 0)

        self.dbox = dbox
        dbox.show_all()
        res = dbox.run()

        if res == Gtk.ResponseType.ACCEPT:
            self.terminal.config.save()

        del (self.dbox)
        dbox.destroy()

        return

    def _create_themes_grid(self, ui):
        grid = Gtk.Grid()
        grid.set_column_spacing(5)
        grid.set_row_spacing(7)
        grid.set_column_homogeneous(True)
        grid.set_row_homogeneous(True)

        scroll_window = self._create_themes_list(ui)

        (combo, search_entry) = self._create_filter_widgets(ui)

        grid.attach(search_entry, 0, 0, 2, 1)
        grid.attach(combo, 2, 0, 1, 1)
        grid.attach(scroll_window, 0, 1, 3, 10)

        return grid

    def _create_filter_widgets(self, ui):

        combo = Gtk.ComboBoxText()
        combo.set_entry_text_column(0)
        combo.connect("changed", self.on_filter_combo_changed)
        combo.append_text("Filter by type")

        for theme_type in ["light", "dark", "All"]:
            combo.append_text(theme_type)

        combo.set_active(0)

        search_entry = Gtk.SearchEntry(max_width_chars=30)
        search_entry.connect("search-changed", self.on_theme_search_changed,
                             ui)

        return [combo, search_entry]

    def _create_themes_list(self, ui):

        profiles_list_model = Gtk.ListStore(str, str, bool, object)
        # Set add/remove buttons availability
        for theme in self.themes_from_repo:
            if theme["name"] in self.profiles:
                profiles_list_model.append(
                    [theme["name"], theme["type"], False, theme])
            else:
                profiles_list_model.append(
                    [theme["name"], theme["type"], True, theme])

        self.current_filter_theme = None
        self.filter_type = "theme_type"
        self.theme_filter = profiles_list_model.filter_new()
        self.theme_filter.set_visible_func(self.theme_filter_func)

        treeview = Gtk.TreeView.new_with_model(self.theme_filter)

        selection = treeview.get_selection()
        selection.set_mode(Gtk.SelectionMode.SINGLE)
        selection.connect("changed", self.on_selection_changed, ui)
        ui['treeview'] = treeview

        for i, column_title in enumerate(["Theme", "Type"]):
            renderer = Gtk.CellRendererText()
            column = Gtk.TreeViewColumn(column_title, renderer, text=i)
            treeview.append_column(column)

        scroll_window = Gtk.ScrolledWindow()
        scroll_window.set_policy(Gtk.PolicyType.AUTOMATIC,
                                 Gtk.PolicyType.AUTOMATIC)
        scroll_window.add(treeview)

        return scroll_window

    def _create_settings_grid(self, ui):
        grid = Gtk.Grid()
        grid.set_column_spacing(5)
        grid.set_row_spacing(7)
        grid.attach(self._create_default_inherits_check(ui), 0, 15, 2, 1)
        grid.attach(Gtk.Label("Available profiles: "), 0, 16, 1, 1)
        grid.attach(self._create_inherits_from_combo(ui), 1, 16, 1, 1)
        grid.attach(
            self._create_main_action_button(ui, "install", self.on_install), 0,
            20, 1, 1)
        grid.attach(
            self._create_main_action_button(ui, "remove", self.on_uninstall),
            1, 20, 1, 1)
        self.theme_preview = ThemePreview(self.themes_from_repo[0])
        grid.attach(self.theme_preview, 0, 10, 4, 2)

        return grid

    def _create_default_inherits_check(self, ui):
        check = Gtk.CheckButton("Inherit preferences from default profile")
        check.set_active(True)
        check.connect("toggled", self.on_inheritsfromdefaultcheck_toggled, ui)
        ui['check_inherits_from_default'] = check

        return check

    def _create_inherits_from_combo(self, ui):
        combo = Gtk.ComboBoxText()
        combo.set_entry_text_column(0)
        combo.set_sensitive(False)
        combo.connect("changed", self.on_inheritsfromcombo_changed, ui)
        ui['inherits_from_combo'] = combo

        for profile in self.profiles:
            combo.append_text(profile)

        combo.set_active(
            self.profiles.index(self.terminal.config.get_profile())
        )  #set current terminal profile as current item

        return combo

    def _create_main_action_button(self, ui, label, action):
        btn = Gtk.Button(_(label.capitalize()))
        btn.connect("clicked", action, ui)
        btn.set_sensitive(False)
        ui['button_' + label] = btn

        return btn

    def theme_filter_func(self, model, iter, data):
        if self.filter_type == "theme_type":
            return self.filter_by_theme_type(model, iter, data)
        else:
            return self.filter_by_theme_search(model, iter, data)

    def filter_by_theme_search(self, model, iter, data):
        return model[iter][0].lower().find(self.current_filter_theme) > -1

    def filter_by_theme_type(self, model, iter, data):
        if self.current_filter_theme is None or self.current_filter_theme == "All":
            return True
        else:
            return model[iter][1] == self.current_filter_theme

    def on_theme_search_changed(self, widget, ui):
        self.filter_type = "theme_search"
        self.current_filter_theme = widget.get_text()
        self.theme_filter.refilter()

    def on_filter_combo_changed(self, widget):

        if widget.get_active() == 0:
            self.current_filter_theme = None
        else:
            self.current_filter_theme = widget.get_active_text()

        self.filter_type = "theme_type"

        # #we update the filter, which updates in turn the view
        self.theme_filter.refilter()

    def on_inheritsfromdefaultcheck_toggled(self, check, data=None):
        if check.get_active() is not True:
            data["inherits_from_combo"].set_sensitive(True)
            self.inherits_config_from = self.profiles[
                data['inherits_from_combo'].get_active()]
        else:
            data["inherits_from_combo"].set_sensitive(False)
            self.inherits_config_from = 'default'

    def on_inheritsfromcombo_changed(self, combo, data):
        if combo.get_sensitive():
            self.inherits_config_from = self.profiles[combo.get_active()]
        else:
            self.inherits_config_from = 'default'

    def on_selection_changed(self, selection, data=None):
        (model, iter) = selection.get_selected()
        data['button_install'].set_sensitive(model[iter][2])
        data['button_remove'].set_sensitive(model[iter][2] is not True)
        self.theme_preview.update_preview(model[iter][3])

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

        # If selected theme is active, sets terminal profile to default before unistalling
        if self.terminal.get_profile() == target:
            widget = self.terminal.get_vte()
            self.terminal.force_set_profile(widget, 'default')

        self.terminal.config.del_profile(target)
        self.terminal.config.save()
        self.update_comboInheritsFrom(data)

        #'Add' button available again
        data['treeview'].get_model().set_value(iter, 2, True)
        self.on_selection_changed(selection, data)

    def on_install(self, button, data):
        treeview = data['treeview']
        selection = treeview.get_selection()
        (store, iter) = selection.get_selected()
        target = store[iter][3]
        widget = self.terminal.get_vte()
        treeview.set_enable_tree_lines(False)

        if not iter:
            return

        self.terminal.config.add_profile(target["name"])
        template_data = self.config_base.profiles[
            self.inherits_config_from].copy()

        for k, v in target.items():
            if k != 'background_image' and k != 'name' and k != 'type':
                if k == 'background_darkness':
                    template_data[k] = float(v)
                else:
                    template_data[k] = v

        for k, v in template_data.items():
            self.config_base.set_item(k, v, target["name"])

        self.terminal.force_set_profile(widget, target["name"])
        self.terminal.config.save()
        self.update_comboInheritsFrom(data)

        # "Remove" button available again
        data['treeview'].get_model().set_value(iter, 2, False)
        self.on_selection_changed(selection, data)
        treeview.set_enable_tree_lines(True)

    def update_comboInheritsFrom(self, data):
        data['inherits_from_combo'].remove_all()
        profiles = self.terminal.config.list_profiles()
        self.profiles = profiles
        for profile in profiles:
            data['inherits_from_combo'].append_text(profile)

        data['inherits_from_combo'].set_active(
            profiles.index(self.terminal.config.get_profile()))
Ejemplo n.º 2
0
class TerminatorThemes(plugin.Plugin):

    capabilities = ['terminal_menu']
    config_base = ConfigBase()
    base_url = 'https://api.github.com/repos/EliverLara/terminator-themes/contents/themes.json'
    inherits_config_from = "default"

    def callback(self, menuitems, menu, terminal):
        """Add our item to the menu"""
        self.terminal = terminal
        item = Gtk.ImageMenuItem(Gtk.STOCK_FIND)
        item.connect('activate', self.configure)
        item.set_label("Themes")
        item.set_sensitive(True)
        menuitems.append(item)

    def configure(self, widget, data=None):
        ui = {}
        dbox = Gtk.Dialog(_("Terminator themes"), None, Gtk.DIALOG_MODAL)

        headers = {"Accept": "application/vnd.github.v3.raw"}
        response = requests.get(self.base_url, headers=headers)

        if response.status_code != 200:
            gerr(_("Failed to get list of available themes"))
            return

        self.themes_from_repo = response.json()["themes"]
        self.profiles = self.terminal.config.list_profiles()

        main_container = Gtk.HBox(spacing=5)
        main_container.pack_start(self._create_themes_list(ui), True, True)
        main_container.pack_start(self._create_settings_grid(ui), True, True,
                                  0)
        dbox.vbox.pack_start(main_container, True, True)

        self.dbox = dbox
        dbox.show_all()
        res = dbox.run()

        if res == Gtk.RESPONSE_ACCEPT:
            self.terminal.config.save()
        del (self.dbox)
        dbox.destroy()

        return

    def _create_themes_list(self, ui):
        liststore = Gtk.ListStore(str, bool, object)
        # Set add/remove buttons availability
        for theme in self.themes_from_repo:
            if theme["name"] in self.profiles:
                liststore.append([theme["name"], False, theme])
            else:
                liststore.append([theme["name"], True, theme])

        treeview = Gtk.TreeView(liststore)

        selection = treeview.get_selection()
        selection.set_mode(Gtk.SELECTION_SINGLE)
        selection.connect("changed", self.on_selection_changed, ui)
        ui['treeview'] = treeview

        renderer_text = Gtk.CellRendererText()
        column_text = Gtk.TreeViewColumn("Theme", renderer_text, text=0)
        treeview.append_column(column_text)

        scroll_window = Gtk.ScrolledWindow()
        scroll_window.set_size_request(300, 250)
        scroll_window.set_policy(Gtk.POLICY_AUTOMATIC, Gtk.POLICY_AUTOMATIC)
        scroll_window.add_with_viewport(treeview)

        return scroll_window

    def _create_settings_grid(self, ui):
        settings_grid = Gtk.VBox(spacing=7)
        settings_grid.set_homogeneous(False)
        settings_grid.pack_start(self._create_default_inherits_check(ui),
                                 False, True)
        settings_grid.pack_start(self._create_inherits_from_grid(ui), False,
                                 True)
        settings_grid.pack_start(self._create_main_actions_grid(ui), False,
                                 True)

        return settings_grid

    def _create_default_inherits_check(self, ui):
        check = Gtk.CheckButton("Inherits preferences from default profile")
        check.set_active(True)
        check.connect("toggled", self.on_inheritsfromdefaultcheck_toggled, ui)
        ui['check_inherits_from_default'] = check

        return check

    def _create_inherits_from_grid(self, ui):
        # Available themes to inherit combo
        combo_model = Gtk.ListStore(str)
        for profile in self.profiles:
            combo_model.append([profile])

        combo = Gtk.ComboBox()
        combo.set_model(combo_model)
        combo_renderer_text = Gtk.CellRendererText()
        combo.pack_start(combo_renderer_text, True)
        combo.add_attribute(combo_renderer_text, "text", 0)
        combo.set_sensitive(False)
        combo.connect("changed", self.on_inheritsfromcombo_changed, ui)
        ui['inherits_from_combo'] = combo
        combo.set_active(
            self.profiles.index(self.terminal.config.get_profile()))

        combo_grid = Gtk.HBox()
        combo_grid.pack_start(Gtk.Label("Available profiles: "), False, True)
        combo_grid.pack_start(combo, False, True)

        return combo_grid

    def _create_main_actions_grid(self, ui):
        # Install/Remove buttons grid
        main_actions_box = Gtk.HBox()
        main_actions_box.pack_start(
            self._create_main_action_button(ui, "install", self.on_install),
            True, True)
        main_actions_box.pack_start(
            self._create_main_action_button(ui, "remove", self.on_uninstall),
            True, True, 0)

        return main_actions_box

    def _create_main_action_button(self, ui, label, action):
        btn = Gtk.Button(_(label.capitalize()))
        btn.connect("clicked", action, ui)
        btn.set_sensitive(False)
        ui['button_' + label] = btn

        return btn

    def on_inheritsfromdefaultcheck_toggled(self, check, data=None):
        if check.get_active() is not True:
            data["inherits_from_combo"].set_sensitive(True)
            self.inherits_config_from = self.profiles[
                data['inherits_from_combo'].get_active()]
        else:
            data["inherits_from_combo"].set_sensitive(False)
            self.inherits_config_from = 'default'

    def on_inheritsfromcombo_changed(self, combo, data):
        if combo.get_sensitive():
            self.inherits_config_from = self.profiles[combo.get_active()]
        else:
            self.inherits_config_from = 'default'

    def on_selection_changed(self, selection, data=None):
        (model, iter) = selection.get_selected()
        data['button_install'].set_sensitive(model[iter][1])
        data['button_remove'].set_sensitive(model[iter][1] is not True)

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

        # If selected theme is active, sets terminal profile to default before unistalling
        if self.terminal.get_profile() == target:
            widget = self.terminal.get_vte()
            self.terminal.force_set_profile(widget, 'default')

        self.terminal.config.del_profile(target)
        self.terminal.config.save()

        data['inherits_from_combo'].set_active(self.profiles.index(target))
        self.update_comboInheritsFrom(data, 2)

        #'Add' button available again
        data["treeview"].get_model().set_value(iter, 1, True)
        self.on_selection_changed(selection, data)

    def on_install(self, button, data):
        treeview = data['treeview']
        selection = treeview.get_selection()
        (store, iter) = selection.get_selected()
        target = store[iter][2]
        widget = self.terminal.get_vte()
        treeview.set_enable_tree_lines(False)

        if not iter:
            return

        # Creates a new profile and overwrites the default colors for the new theme
        self.terminal.config.add_profile(target["name"])
        template_data = self.config_base.profiles[
            self.inherits_config_from].copy()

        for k, v in target.items():
            if k != 'background_image' and k != 'name' and k != 'type':
                if k == 'background_darkness':
                    template_data[k] = float(v)
                else:
                    template_data[k] = v

        for k, v in template_data.items():
            self.config_base.set_item(k, v, target["name"])

        self.terminal.force_set_profile(widget, target["name"])
        self.terminal.config.save()
        self.update_comboInheritsFrom(data, 1, target["name"])

        # "Remove" button available again
        data["treeview"].get_model().set_value(iter, 1, False)
        self.on_selection_changed(selection, data)
        treeview.set_enable_tree_lines(True)

    def update_comboInheritsFrom(self, data, action=1, target=None):
        profiles = self.terminal.config.list_profiles()
        self.profiles = profiles
        data["inherits_from_combo"].get_model().clear()
        for profile in profiles:
            data["inherits_from_combo"].get_model().append([profile])

        data['inherits_from_combo'].set_active(
            profiles.index(self.terminal.config.get_profile()))
Ejemplo n.º 3
0
class TerminatorThemes(plugin.Plugin):

    capabilities = ['terminal_menu']
    config_base = ConfigBase()
    base_url = 'https://api.github.com/repos/EliverLara/terminator-themes/contents/schemes'

    def callback(self, menuitems, menu, terminal):
        """Add our item to the menu"""
        self.terminal = terminal
        item = Gtk.ImageMenuItem(Gtk.STOCK_FIND)
        item.connect('activate', self.configure)
        item.set_label("Themes")
        item.set_sensitive(True)
        menuitems.append(item)

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

        dbox = Gtk.Dialog(_("Terminator themes"), None, Gtk.DialogFlags.MODAL,
                          (_("_Close"), Gtk.ResponseType.ACCEPT))

        self.liststore = Gtk.ListStore(str, bool)

        profiles_from_repo = []
        response = requests.get(self.base_url)

        if response.status_code != 200:
            gerr(_("Failed to get list of available themes"))
            return

        for repo in response.json():
            profiles_from_repo.append(repo['name'])

        profiles = self.terminal.config.list_profiles()

        # Set add/remove buttons availability
        for profile in profiles_from_repo:
            profile = profile.split(".")
            if profile[0] in profiles:
                self.liststore.append([profile[0], False])
            else:
                self.liststore.append([profile[0], True])

        treeview = Gtk.TreeView(self.liststore)

        selection = treeview.get_selection()

        selection.set_mode(Gtk.SelectionMode.SINGLE)
        selection.connect("changed", self.on_selection_changed, ui)
        ui['treeview'] = treeview

        renderer_text = Gtk.CellRendererText()
        column_text = Gtk.TreeViewColumn("Theme", renderer_text, text=0)
        treeview.append_column(column_text)

        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(_("Install"))
        button_box.pack_start(button, False, True, 0)
        button.connect("clicked", self.on_install, ui)
        button.set_sensitive(False)
        ui['button_install'] = button

        button = Gtk.Button(_("Remove"))
        button_box.pack_start(button, False, True, 0)
        button.connect("clicked", self.on_uninstall, ui)
        button.set_sensitive(False)
        ui['button_uninstall'] = button

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

    def on_selection_changed(self, selection, data=None):
        (model, iter) = selection.get_selected()
        data['button_install'].set_sensitive(model[iter][1])
        data['button_uninstall'].set_sensitive(model[iter][1] is not True)

    def on_uninstall(self, button, data):

        treeview = data['treeview']
        selection = treeview.get_selection()
        (store, iter) = selection.get_selected()
        target = store[iter][0]

        # If selected theme is active, sets terminal profile to default before unistalling
        if self.terminal.get_profile() == target:
            widget = self.terminal.get_vte()
            self.terminal.force_set_profile(widget, 'default')

        self.terminal.config.del_profile(target)
        self.terminal.config.save()

        #'Add' button available again
        self.liststore.set_value(iter, 1, True)
        self.on_selection_changed(selection, data)

    def on_install(self, button, data):
        treeview = data['treeview']
        selection = treeview.get_selection()
        (store, iter) = selection.get_selected()
        target = store[iter][0]
        widget = self.terminal.get_vte()
        treeview.set_enable_tree_lines(False)

        if not iter:
            return

        headers = {"Accept": "application/vnd.github.v3.raw"}
        response = requests.get(self.base_url + '/' + target + '.config',
                                headers=headers)

        if response.status_code != 200:
            gerr(_("Failed to download selected theme"))
            return

        # Creates a new profile and overwrites the default colors for the new theme
        self.terminal.config.add_profile(target)
        target_data = self.make_dictionary(response.content)
        for k, v in target_data.items():
            if k != 'background_image':
                self.config_base.set_item(k, v[1:-1], target)

        self.terminal.force_set_profile(widget, target)
        self.terminal.config.save()

        # "Remove" button available again
        self.liststore.set_value(iter, 1, False)
        self.on_selection_changed(selection, data)
        treeview.set_enable_tree_lines(True)

    def make_dictionary(self, data):
        arr = []
        out_dict = {}
        for line in data.split("\n"):
            arr.append(line.split("="))

        for item in arr:
            if len(item) > 1:
                out_dict[item[0].strip()] = item[1].strip()

        return out_dict
Ejemplo n.º 4
0
class Lara(plugin.Plugin):

    capabilities = ['terminal_menu']
    config_base = ConfigBase()
    selected_theme = "Some" #selected theme data
    selected_theme_label = "Some"
    previous_selected_theme_label = Gtk.Label("Some")
    colors = {
        "available": "#3f953a",
        "installed": "#DE4D60",
        "selected" : "#fc2"
    }
    def callback(self, menuitems, menu, terminal):
        """Add our item to the menu"""
        self.terminal = terminal
        item = Gtk.ImageMenuItem(Gtk.STOCK_FIND)
        item.connect('activate', self.configure)
        item.set_label("Lara")
        item.set_sensitive(True)
        menuitems.append(item)

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

        win = Gtk.Window()
        win.set_border_width(10)
        win.set_default_size(700, 400)

        win.set_titlebar(self.make_headerbar(ui))

        # Fill thmmes containers
        self.profiles = self.terminal.config.list_profiles()

        response = requests.get("https://git.io/fxtUa")

        if response.status_code != 200:
            gerr(_("Failed to get list of available themes"))
            return

        dark_themes = self.make_themes_container(ui, filter(lambda x: x['type'] == 'dark', response.json()["themes"]))
        light_themes = self.make_themes_container(ui, filter(lambda x: x['type'] == 'light', response.json()["themes"]))
       
        main_container = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=3)
        main_container.set_homogeneous(False)
        win.add(main_container)

        ui["stack"].add_titled(dark_themes, "check", "Dark themes")
        ui["stack"].add_titled(light_themes, "label", "Light themes")

        # Box to center stack horizontally
      

        # searchContainer = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, halign=Gtk.Align.CENTER)
        # search_entry = Gtk.SearchEntry(max_width_chars=45)
        # search_entry.connect("search-changed", self.on_search_changed, ui)
        # search_entry.show()
        # searchContainer.add(search_entry)
        # ui["search_entry"] = search_entry

        # for i in range(220):

        #     main_container.pack_start(Gtk.Button("test"), True, True, 1)
      
       # main_container.pack_start(searchContainer, False, False, 1)
        main_container.pack_start(ui["stack"], True, True, 1)

        win.show_all()

    def make_headerbar(self, ui):
        
        header = Gtk.HeaderBar()
        header.props.show_close_button = True
       # header.set_subtitle(self.selected_theme_label)
        button_install = Gtk.Button(_("Install"))
        button_uninstall = Gtk.Button(_("Remove"))
        button_install.set_sensitive(False)
        button_uninstall.set_sensitive(False)
        button_uninstall.connect("clicked", self.on_uninstall, ui) 
        button_install.connect("clicked", self.on_install, ui) 

        ui["button_install"] = button_install
        ui["button_uninstall"] = button_uninstall

        header.pack_end(button_install)
        header.pack_end(button_uninstall)

        stack = Gtk.Stack()
        stack.set_transition_type(Gtk.StackTransitionType.SLIDE_LEFT_RIGHT)
        stack.set_transition_duration(500)
        stack.set_hhomogeneous(True)    

        stack_switcher = Gtk.StackSwitcher()
        stack_switcher.set_stack(stack)

        stackBox = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=0)
        stackBox.set_homogeneous(False)
        stackBox.pack_start(stack_switcher, True, False, 0)

        header.set_custom_title(stackBox)
        
        ui["header"] = header
        ui["stack"] = stack
        return header

    def make_themes_container(self, ui, themes):
      
        themes_scrolled = Gtk.ScrolledWindow()
        themes_scrolled.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC)

        themes_flowbox = Gtk.FlowBox()
        themes_flowbox.set_valign(Gtk.Align.START)
        
        themes_flowbox.set_min_children_per_line(3)
        themes_flowbox.set_selection_mode(Gtk.SelectionMode.NONE)
        themes_scrolled.add(themes_flowbox)

        for theme in themes:
            card = self.create_theme_card(theme, ui)   
            themes_flowbox.add(card)

        return themes_scrolled


    def on_search_changed(self, widget, ui):
        print ui["search_entry"].get_text()
        ui["items_container"].set_filter_func(self.filter_themes, ui["search_entry"].get_text())

    def filter_themes(self, widget, target):
       # self.dump(widget)
        # if target == "la":
        #     return True
        # return False
        print widget.name


    def on_uninstall(self, button, ui):
 
        target = self.selected_theme["name"]

        # If selected theme is active, sets terminal profile to default before unistalling
        if self.terminal.get_profile() == target:
            widget = self.terminal.get_vte()
            self.terminal.force_set_profile(widget, 'default')

        self.terminal.config.del_profile(target)
        self.terminal.config.save()
        self.profiles = self.terminal.config.list_profiles()

        #'Install' button available again
        self.on_selection_changed(button, ui, self.selected_theme, self.selected_theme_label)

    def on_install(self, button, ui):
      
        target = self.selected_theme
        widget = self.terminal.get_vte()
        theme_name = target["name"]
        self.terminal.config.add_profile(theme_name) 
        for k, v in target.items():
            if k != 'background_image' and k != 'name' and k != 'type':
                self.config_base.set_item(k, v, theme_name)

        self.terminal.force_set_profile(widget, theme_name)
        self.terminal.config.save()
        self.profiles = self.terminal.config.list_profiles()
        # To change install/remove button state
        self.on_selection_changed(button, ui, self.selected_theme, self.selected_theme_label)

    
    def on_selection_changed(self, button, ui, theme, label):

        target = theme["name"]

        ui["header"].set_subtitle(target + " Selected")
        ui["button_uninstall"].set_sensitive(target in self.profiles)
        ui["button_install"].set_sensitive(target not in self.profiles)

        # Sets avaailability colors for the previous selected theme
        if  self.previous_selected_theme_label.get_text() not in self.profiles:
            self.previous_selected_theme_label.modify_fg(0, color = Gdk.color_parse(self.colors["available"])) 
        else:
            self.previous_selected_theme_label.modify_fg(0, color = Gdk.color_parse(self.colors["installed"])) 
            
        self.selected_theme = theme
        self.selected_theme_label = label

        # Check if some theme have been selected
        if self.selected_theme_label != "Some" :
            self.selected_theme_label.modify_fg(0, color = Gdk.color_parse(self.colors["selected"]))  
            self.previous_selected_theme_label = self.selected_theme_label  


    def create_theme_card(self, theme, ui):

        theme_card = Gtk.Button()
        label = Gtk.Label(theme["name"])
        grid = Gtk.VBox(spacing=2)
        
        theme_pallete = self.create_theme_palette(theme)

        grid.pack_start (theme_pallete, True, True,0)
        grid.pack_start (label, True,True,0)
    
        if theme["name"] in self.profiles:
            label.modify_fg(0, color = Gdk.color_parse(self.colors["installed"])) 
        else:
            label.modify_fg(0, color = Gdk.color_parse(self.colors["available"])) 
       
        theme_card.connect("clicked", self.on_selection_changed, ui, theme, label) 
        theme_card.add(grid)
        
        return theme_card


    def create_theme_palette(self, data):

        theme_pallete_grid = Gtk.VBox()

        flowbox = Gtk.FlowBox()
        flowbox.set_valign(Gtk.Align.START)
        flowbox.set_min_children_per_line(4)
        flowbox.set_max_children_per_line(4)
        flowbox.set_selection_mode(Gtk.SelectionMode.NONE)

        area = Gtk.DrawingArea()
        area.set_size_request(170, 40)

        if data.has_key('background_color'):
            theme_pallete_grid.modify_bg(0, color = Gdk.color_parse(data['background_color'])) 
            
        for color in data['palette'].split(":")[0:8]:
            btn = Gtk.ColorButton()
            btn.set_color(color = Gdk.color_parse(color)) 
            flowbox.add(btn)

        theme_pallete_grid.pack_start (area, True, True,0)
        theme_pallete_grid.pack_start (flowbox, True,True,0)

        return theme_pallete_grid
class TerminatorThemes(plugin.Plugin):

    capabilities = ['terminal_menu']
    config_base = ConfigBase()
    base_url = 'https://api.github.com/repos/EliverLara/terminator-themes/contents/schemes'
    inherits_config_from = "default"

    def callback(self, menuitems, menu, terminal):
        """Add our item to the menu"""
        self.terminal = terminal
        item = Gtk.ImageMenuItem(Gtk.STOCK_FIND)
        item.connect('activate', self.configure)
        item.set_label("Themes")
        item.set_sensitive(True)
        menuitems.append(item)

    def configure(self, widget, data=None):
        ui = {}
        dbox = Gtk.Dialog(_("Terminator themes"), None, Gtk.DialogFlags.MODAL)

        self.profiles_from_repo = []
        response = requests.get(self.base_url)

        if response.status_code != 200:
            gerr(_("Failed to get list of available themes"))
            return

        for repo in response.json():
            self.profiles_from_repo.append(repo['name'])

        self.profiles = self.terminal.config.list_profiles()

        main_container = Gtk.HBox(spacing=7)
        main_container.pack_start(self._create_themes_list(ui), True, True, 0)
        main_container.pack_start(self._create_settings_grid(ui), True, True,
                                  0)
        dbox.vbox.pack_start(main_container, True, True, 0)

        self.dbox = dbox
        dbox.show_all()
        res = dbox.run()

        if res == Gtk.ResponseType.ACCEPT:
            self.terminal.config.save()

        del (self.dbox)
        dbox.destroy()
        return

    def _create_themes_list(self, ui):
        profiles_list_model = Gtk.ListStore(str, bool)
        # Set add/remove buttons availability
        for profile in self.profiles_from_repo:
            profile = profile.split(".")
            if profile[0] in self.profiles:
                profiles_list_model.append([profile[0], False])
            else:
                profiles_list_model.append([profile[0], True])

        treeview = Gtk.TreeView(profiles_list_model)

        selection = treeview.get_selection()
        selection.set_mode(Gtk.SelectionMode.SINGLE)
        selection.connect("changed", self.on_selection_changed, ui)
        ui['treeview'] = treeview

        renderer_text = Gtk.CellRendererText()
        column_text = Gtk.TreeViewColumn("Theme", renderer_text, text=0)
        treeview.append_column(column_text)

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

        return scroll_window

    def _create_settings_grid(self, ui):
        grid = Gtk.Grid()
        grid.set_column_spacing(5)
        grid.set_row_spacing(7)
        grid.attach(self._create_default_inherits_check(ui), 0, 0, 2, 1)
        grid.attach(Gtk.Label("Available profiles: "), 0, 1, 1, 1)
        grid.attach(self._create_inherits_from_combo(ui), 1, 1, 1, 1)
        grid.attach(
            self._create_main_action_button(ui, "install", self.on_install), 0,
            4, 1, 1)
        grid.attach(
            self._create_main_action_button(ui, "remove", self.on_uninstall),
            1, 4, 1, 1)

        return grid

    def _create_default_inherits_check(self, ui):
        check = Gtk.CheckButton("Inherit preferences from default profile")
        check.set_active(True)
        check.connect("toggled", self.on_inheritsfromdefaultcheck_toggled, ui)
        ui['check_inherits_from_default'] = check

        return check

    def _create_inherits_from_combo(self, ui):
        combo = Gtk.ComboBoxText()
        combo.set_entry_text_column(0)
        combo.set_sensitive(False)
        combo.connect("changed", self.on_inheritsfromcombo_changed, ui)
        ui['inherits_from_combo'] = combo

        for profile in self.profiles:
            combo.append_text(profile)

        combo.set_active(
            self.profiles.index(self.terminal.config.get_profile()))

        return combo

    def _create_main_action_button(self, ui, label, action):
        btn = Gtk.Button(_(label.capitalize()))
        btn.connect("clicked", action, ui)
        btn.set_sensitive(False)
        ui['button_' + label] = btn

        return btn

    def on_inheritsfromdefaultcheck_toggled(self, check, data=None):
        if check.get_active() is not True:
            data["inherits_from_combo"].set_sensitive(True)
            self.inherits_config_from = self.profiles[
                data['inherits_from_combo'].get_active()]
        else:
            data["inherits_from_combo"].set_sensitive(False)
            self.inherits_config_from = 'default'

    def on_inheritsfromcombo_changed(self, combo, data):
        if combo.get_sensitive():
            self.inherits_config_from = self.profiles[combo.get_active()]
        else:
            self.inherits_config_from = 'default'

    def on_selection_changed(self, selection, data=None):
        (model, iter) = selection.get_selected()
        data['button_install'].set_sensitive(model[iter][1])
        data['button_remove'].set_sensitive(model[iter][1] is not True)

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

        # If selected theme is active, sets terminal profile to default before unistalling
        if self.terminal.get_profile() == target:
            widget = self.terminal.get_vte()
            self.terminal.force_set_profile(widget, 'default')

        self.terminal.config.del_profile(target)
        self.terminal.config.save()
        self.update_comboInheritsFrom(data)

        #'Add' button available again
        data['treeview'].get_model().set_value(iter, 1, True)
        self.on_selection_changed(selection, data)

    def on_install(self, button, data):
        treeview = data['treeview']
        selection = treeview.get_selection()
        (store, iter) = selection.get_selected()
        target = store[iter][0]
        widget = self.terminal.get_vte()
        treeview.set_enable_tree_lines(False)

        if not iter:
            return

        headers = {"Accept": "application/vnd.github.v3.raw"}
        response = requests.get(self.base_url + '/' + target + '.config',
                                headers=headers)

        if response.status_code != 200:
            gerr(_("Failed to download selected theme"))
            return

        # creates a new profile and overwrites the default colors for the new theme
        self.terminal.config.add_profile(target)
        target_data = self.make_dictionary(response.content)
        template_data = self.config_base.profiles[
            self.inherits_config_from].copy()

        for k, v in target_data.items():
            if k == 'background_darkness':
                template_data[k] = float(v)
            elif k == 'background_type':
                template_data[k] = v
            else:
                template_data[k] = v[1:-1]

        for k, v in template_data.items():
            if k != 'background_image':
                self.config_base.set_item(k, v, target)

        self.terminal.force_set_profile(widget, target)
        self.terminal.config.save()
        self.update_comboInheritsFrom(data)

        # "Remove" button available again
        data['treeview'].get_model().set_value(iter, 1, False)
        self.on_selection_changed(selection, data)
        treeview.set_enable_tree_lines(True)

    def update_comboInheritsFrom(self, data):
        data['inherits_from_combo'].remove_all()
        profiles = self.terminal.config.list_profiles()
        for profile in profiles:
            data['inherits_from_combo'].append_text(profile)

        data['inherits_from_combo'].set_active(
            profiles.index(self.terminal.config.get_profile()))
        self.profiles = profiles

    def make_dictionary(self, data):
        arr = []
        out_dict = {}
        for line in data.split("\n"):
            arr.append(line.split("="))

        for item in arr:
            if len(item) > 1:
                out_dict[item[0].strip()] = item[1].strip()

        return out_dict