# Copyright (C) 2005 Travis Shirk # Vincent Hanquez # Copyright (C) 2005-2014 Yann Leboulanger # Copyright (C) 2005-2007 Nikos Kouremenos # Copyright (C) 2006 Dimitur Kirov # Copyright (C) 2006-2007 Jean-Marie Traissard # # This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . from enum import IntEnum from enum import unique from gi.repository import Gdk from gi.repository import Gtk from gi.repository import Pango from gajim.common import app from gajim.common.i18n import _ from gajim.common.i18n import p_ from gajim.common.setting_values import ADVANCED_SETTINGS from gajim.common.setting_values import APP_SETTINGS from gajim.gtk.builder import get_builder @unique class Column(IntEnum): NAME = 0 VALUE = 1 TYPE = 2 IS_DEFAULT = 3 BOOL_DICT = { True: _('Activated'), False: _('Deactivated') } SETTING_TYPES = { bool: p_('Configuration type', 'Boolean'), int: p_('Configuration type', 'Integer'), str: p_('Configuration type', 'Text'), } class AdvancedConfig(Gtk.ApplicationWindow): def __init__(self) -> None: Gtk.ApplicationWindow.__init__(self) self.set_application(app.app) self.set_position(Gtk.WindowPosition.CENTER) self.set_show_menubar(False) self.set_name('AdvancedConfig') self.set_title(_('Advanced Configuration Editor (ACE)')) self._ui = get_builder('advanced_configuration.ui') self.add(self._ui.box) treeview = self._ui.advanced_treeview self.treeview = treeview self.model = Gtk.TreeStore(str, str, str, bool) self._fill_model() self.model.set_sort_column_id(0, Gtk.SortType.ASCENDING) self.modelfilter = self.model.filter_new() self.modelfilter.set_visible_func(self._visible_func) renderer_text = Gtk.CellRendererText() renderer_text.set_property('ellipsize', Pango.EllipsizeMode.END) col = Gtk.TreeViewColumn(p_('Configuration', 'Preference Name'), renderer_text, text=0) treeview.insert_column(col, -1) col.set_cell_data_func(renderer_text, self._value_column_name_callback) col.set_expand(True) col.set_sizing(Gtk.TreeViewColumnSizing.FIXED) col.set_resizable(True) self.renderer_text = Gtk.CellRendererText() self.renderer_text.connect('edited', self._on_config_edited) self.renderer_text.set_property('ellipsize', Pango.EllipsizeMode.END) col = Gtk.TreeViewColumn( p_('Configuration', 'Value'), self.renderer_text, text=1) treeview.insert_column(col, -1) col.set_cell_data_func(self.renderer_text, self._value_column_data_callback) col.set_expand(True) col.set_sizing(Gtk.TreeViewColumnSizing.FIXED) col.set_resizable(True) renderer_text = Gtk.CellRendererText() col = Gtk.TreeViewColumn( p_('Configuration', 'Type'), renderer_text, text=2) treeview.insert_column(col, -1) col.set_sizing(Gtk.TreeViewColumnSizing.FIXED) treeview.set_model(self.modelfilter) self.connect_after('key-press-event', self._on_key_press) self._ui.connect_signals(self) self.show_all() def _on_key_press(self, _widget: Gtk.Widget, event: Gdk.EventKey) -> None: if event.keyval != Gdk.KEY_Escape: return if self._ui.search_entry.get_text(): self._ui.search_entry.set_text('') return self.destroy() def _value_column_name_callback(self, _col: Gtk.TreeViewColumn, cell: Gtk.CellRenderer, model: Gtk.TreeModel, iter_: Gtk.TreeIter, _data: object | None ) -> None: opt_is_default = model[iter_][Column.IS_DEFAULT] cell.set_property('weight', 400 if opt_is_default else 700) def _value_column_data_callback(self, _col: Gtk.TreeViewColumn, cell: Gtk.CellRenderer, model: Gtk.TreeModel, iter_: Gtk.TreeIter, _data: object | None ) -> None: opt_type = model[iter_][Column.TYPE] cell.set_property('editable', opt_type != SETTING_TYPES[bool]) opt_is_default = model[iter_][Column.IS_DEFAULT] cell.set_property('weight', 400 if opt_is_default else 700) def _on_treeview_selection_changed(self, treeselection: Gtk.TreeSelection ) -> None: model, iter_ = treeselection.get_selected() if not iter_: self._ui.reset_button.set_sensitive(False) return setting = model[iter_][Column.NAME] desc = ADVANCED_SETTINGS['app'][setting] self._ui.description.set_text( desc or p_('Configuration description', 'None')) self._ui.reset_button.set_sensitive(not model[iter_][Column.IS_DEFAULT]) def _on_treeview_row_activated(self, _treeview: Gtk.TreeView, path: Gtk.TreePath, _column: Gtk.TreeViewColumn ) -> None: modelpath = self.modelfilter.convert_path_to_child_path(path) assert modelpath modelrow = self.model[modelpath] setting = modelrow[Column.NAME] if modelrow[Column.TYPE] != SETTING_TYPES[bool]: return setting_value = modelrow[Column.VALUE] != _('Activated') column_value = BOOL_DICT[setting_value] default = APP_SETTINGS[setting] app.settings.set(setting, setting_value) modelrow[Column.VALUE] = column_value modelrow[Column.IS_DEFAULT] = bool(setting_value == default) self._ui.reset_button.set_sensitive(setting_value != default) def _on_config_edited(self, _cell: Gtk.CellRendererText, path: str, text: str ) -> None: treepath = Gtk.TreePath.new_from_string(path) modelpath = self.modelfilter.convert_path_to_child_path(treepath) assert modelpath modelrow = self.model[modelpath] setting = modelrow[Column.NAME] default = APP_SETTINGS[setting] value = text if modelrow[Column.TYPE] == SETTING_TYPES[int]: try: value = int(text) except ValueError: return app.settings.set(setting, value) modelrow[Column.VALUE] = text modelrow[Column.IS_DEFAULT] = bool(value == default) self._ui.reset_button.set_sensitive(value != default) def _on_reset_button_clicked(self, button: Gtk.Button) -> None: model, iter_ = self.treeview.get_selection().get_selected() if not iter_: return setting = model[iter_][Column.NAME] default = APP_SETTINGS[setting] if isinstance(default, bool): model[iter_][Column.VALUE] = BOOL_DICT[default] else: model[iter_][Column.VALUE] = str(default) model[iter_][Column.IS_DEFAULT] = True app.settings.set(setting, default) button.set_sensitive(False) def _fill_model(self) -> None: for category, settings in ADVANCED_SETTINGS.items(): if category != 'app': continue for setting in settings: value = app.settings.get(setting) default = APP_SETTINGS[setting] is_default = bool(value == default) if isinstance(value, bool): value = BOOL_DICT[value] type_ = SETTING_TYPES[bool] elif isinstance(value, int): value = str(value) type_ = SETTING_TYPES[int] elif isinstance(value, str): type_ = SETTING_TYPES[str] else: raise ValueError self.model.append(None, [setting, value, type_, is_default]) def _visible_func(self, model: Gtk.TreeModel, treeiter: Gtk.TreeIter, _data: object | None ) -> bool: search_string = self._ui.search_entry.get_text().lower() if not search_string: return True setting = model[treeiter][Column.NAME] desc = ADVANCED_SETTINGS['app'][setting] if search_string in setting or search_string in desc.lower(): return True return False def _on_search_entry_changed(self, _entry: Gtk.SearchEntry) -> None: self.modelfilter.refilter()