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