ability to reset options to default value. Fixes #4465
This commit is contained in:
parent
75c495979c
commit
444bed2784
|
@ -1,24 +1,25 @@
|
|||
<?xml version="1.0"?>
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<interface>
|
||||
<requires lib="gtk+" version="2.16"/>
|
||||
<!-- interface-naming-policy toplevel-contextual -->
|
||||
<object class="GtkWindow" id="advanced_configuration_window">
|
||||
<property name="can_focus">False</property>
|
||||
<property name="border_width">6</property>
|
||||
<property name="title" translatable="yes">Advanced Configuration Editor</property>
|
||||
<property name="role">ace</property>
|
||||
<property name="default_width">650</property>
|
||||
<property name="default_height">540</property>
|
||||
<property name="type_hint">dialog</property>
|
||||
<signal name="destroy" handler="on_advanced_configuration_window_destroy"/>
|
||||
<signal name="destroy" handler="on_advanced_configuration_window_destroy" swapped="no"/>
|
||||
<child>
|
||||
<object class="GtkVBox" id="vbox70">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="border_width">6</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="spacing">6</property>
|
||||
<child>
|
||||
<object class="GtkTable" id="table26">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="n_rows">2</property>
|
||||
<property name="n_columns">2</property>
|
||||
<property name="column_spacing">12</property>
|
||||
|
@ -26,6 +27,7 @@
|
|||
<child>
|
||||
<object class="GtkLabel" id="label248">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="label" translatable="yes">Filter:</property>
|
||||
</object>
|
||||
|
@ -38,7 +40,7 @@
|
|||
<object class="GtkEntry" id="advanced_entry">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<signal name="changed" handler="on_advanced_entry_changed"/>
|
||||
<signal name="changed" handler="on_advanced_entry_changed" swapped="no"/>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
|
@ -51,14 +53,16 @@
|
|||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="hscrollbar_policy">never</property>
|
||||
<property name="vscrollbar_policy">automatic</property>
|
||||
<property name="shadow_type">in</property>
|
||||
<child>
|
||||
<object class="GtkTreeView" id="advanced_treeview">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="rules_hint">True</property>
|
||||
<signal name="row_activated" handler="on_advanced_treeview_row_activated"/>
|
||||
<signal name="row-activated" handler="on_advanced_treeview_row_activated" swapped="no"/>
|
||||
<child internal-child="selection">
|
||||
<object class="GtkTreeSelection" id="treeview-selection1"/>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
|
@ -71,23 +75,28 @@
|
|||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkFrame" id="frame36">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="border_width">3</property>
|
||||
<property name="label_xalign">0</property>
|
||||
<property name="shadow_type">none</property>
|
||||
<child>
|
||||
<object class="GtkAlignment" id="alignment90">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="border_width">6</property>
|
||||
<property name="left_padding">12</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="advanced_desc_label">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="wrap">True</property>
|
||||
</object>
|
||||
|
@ -97,6 +106,7 @@
|
|||
<child type="label">
|
||||
<object class="GtkLabel" id="label357">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label" translatable="yes"><b>Description</b></property>
|
||||
<property name="use_markup">True</property>
|
||||
</object>
|
||||
|
@ -104,11 +114,13 @@
|
|||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="restart_label">
|
||||
<property name="can_focus">False</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="label" translatable="yes"><b>NOTE:</b> You should restart Gajim for some settings to take effect</property>
|
||||
<property name="use_markup">True</property>
|
||||
|
@ -123,27 +135,50 @@
|
|||
<child>
|
||||
<object class="GtkHButtonBox" id="hbuttonbox18">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="spacing">6</property>
|
||||
<property name="layout_style">end</property>
|
||||
<child>
|
||||
<object class="GtkButton" id="reset_button">
|
||||
<property name="label" translatable="yes">_Reset to default</property>
|
||||
<property name="use_action_appearance">False</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="sensitive">False</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="use_action_appearance">False</property>
|
||||
<property name="image">image1</property>
|
||||
<property name="use_underline">True</property>
|
||||
<signal name="clicked" handler="on_reset_button_clicked" swapped="no"/>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="advanced_close_button">
|
||||
<property name="label">gtk-close</property>
|
||||
<property name="use_action_appearance">False</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="can_default">True</property>
|
||||
<property name="receives_default">False</property>
|
||||
<property name="use_action_appearance">False</property>
|
||||
<property name="use_stock">True</property>
|
||||
<signal name="clicked" handler="on_advanced_close_button_clicked"/>
|
||||
<signal name="clicked" handler="on_advanced_close_button_clicked" swapped="no"/>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">0</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="padding">6</property>
|
||||
<property name="position">3</property>
|
||||
</packing>
|
||||
|
@ -151,4 +186,9 @@
|
|||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<object class="GtkImage" id="image1">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="stock">gtk-undo</property>
|
||||
</object>
|
||||
</interface>
|
||||
|
|
|
@ -501,7 +501,7 @@ if dbus_support.supported:
|
|||
for node in path:
|
||||
key += node + '#'
|
||||
key += name
|
||||
prefs_dict[DBUS_STRING(key)] = DBUS_STRING(value[1])
|
||||
prefs_dict[DBUS_STRING(key)] = DBUS_STRING(value)
|
||||
gajim.config.foreach(get_prefs)
|
||||
return prefs_dict
|
||||
|
||||
|
|
|
@ -81,6 +81,7 @@ class AdvancedConfigurationWindow(object):
|
|||
self.entry = self.xml.get_object('advanced_entry')
|
||||
self.desc_label = self.xml.get_object('advanced_desc_label')
|
||||
self.restart_label = self.xml.get_object('restart_label')
|
||||
self.reset_button = self.xml.get_object('reset_button')
|
||||
|
||||
# Format:
|
||||
# key = option name (root/subopt/opt separated by \n then)
|
||||
|
@ -174,6 +175,13 @@ class AdvancedConfigurationWindow(object):
|
|||
else:
|
||||
#we talk about option description in advanced configuration editor
|
||||
self.desc_label.set_text(_('(None)'))
|
||||
if len(opt_path) == 3 or (len(opt_path) == 1 and not \
|
||||
model.iter_has_child(iter_)):
|
||||
self.reset_button.set_sensitive(True)
|
||||
else:
|
||||
self.reset_button.set_sensitive(False)
|
||||
else:
|
||||
self.reset_button.set_sensitive(False)
|
||||
|
||||
def remember_option(self, option, oldval, newval):
|
||||
if option in self.changed_opts:
|
||||
|
@ -195,7 +203,6 @@ class AdvancedConfigurationWindow(object):
|
|||
optname = optnamerow[0].decode('utf-8')
|
||||
keyrow = self.model[modelpath[:2]]
|
||||
key = keyrow[0].decode('utf-8')
|
||||
gajim.config.get_desc_per(optname, key, option)
|
||||
self.remember_option(option + '\n' + key + '\n' + optname,
|
||||
modelrow[1], newval)
|
||||
gajim.config.set_per(optname, key, option, newval)
|
||||
|
@ -244,6 +251,42 @@ class AdvancedConfigurationWindow(object):
|
|||
def on_advanced_configuration_window_destroy(self, widget):
|
||||
del gajim.interface.instances['advanced_config']
|
||||
|
||||
def on_reset_button_clicked(self, widget):
|
||||
model, iter_ = self.treeview.get_selection().get_selected()
|
||||
# Check for GtkTreeIter
|
||||
if iter_:
|
||||
path = model.get_path(iter_)
|
||||
opt_path = self.get_option_path(model, iter_)
|
||||
if len(opt_path) == 1:
|
||||
default = gajim.config.get_default(opt_path[0])
|
||||
elif len(opt_path) == 3:
|
||||
default = gajim.config.get_default_per(opt_path[2], opt_path[0])
|
||||
|
||||
if model[iter_][C_TYPE] == self.types['boolean']:
|
||||
if self.right_true_dict[default] == model[iter_][C_VALUE]:
|
||||
return
|
||||
modelpath = self.modelfilter.convert_path_to_child_path(path)
|
||||
modelrow = self.model[modelpath]
|
||||
option = modelrow[0].decode('utf-8')
|
||||
if len(modelpath) > 1:
|
||||
optnamerow = self.model[modelpath[0]]
|
||||
optname = optnamerow[0].decode('utf-8')
|
||||
keyrow = self.model[modelpath[:2]]
|
||||
key = keyrow[0].decode('utf-8')
|
||||
self.remember_option(option + '\n' + key + '\n' + optname,
|
||||
modelrow[C_VALUE], default)
|
||||
gajim.config.set_per(optname, key, option, default)
|
||||
else:
|
||||
self.remember_option(option, modelrow[C_VALUE], default)
|
||||
gajim.config.set(option, default)
|
||||
gajim.interface.save_config()
|
||||
modelrow[C_VALUE] = self.right_true_dict[default]
|
||||
self.check_for_restart()
|
||||
else:
|
||||
if str(default) == model[iter_][C_VALUE]:
|
||||
return
|
||||
self.on_config_edited(None, path, str(default))
|
||||
|
||||
def on_advanced_close_button_clicked(self, widget):
|
||||
self.window.destroy()
|
||||
|
||||
|
@ -254,14 +297,18 @@ class AdvancedConfigurationWindow(object):
|
|||
newparent = self.model.append(parent, [name, '', ''])
|
||||
self.fill_model(item, newparent)
|
||||
else: # Leaf
|
||||
type_ = self.types[option[OPT_TYPE][0]]
|
||||
if len(item) == 1:
|
||||
type_ = self.types[gajim.config.get_type(name)]
|
||||
elif len(item) == 3:
|
||||
type_ = self.types[gajim.config.get_type_per(item[0],
|
||||
item[2])]
|
||||
if name == 'password':
|
||||
value = _('Hidden')
|
||||
else:
|
||||
if type_ == self.types['boolean']:
|
||||
value = self.right_true_dict[option[OPT_VAL]]
|
||||
value = self.right_true_dict[option]
|
||||
else:
|
||||
value = option[OPT_VAL]
|
||||
value = option
|
||||
self.model.append(parent, [name, value, type_])
|
||||
|
||||
def visible_func(self, model, treeiter):
|
||||
|
|
|
@ -65,7 +65,7 @@ class Config:
|
|||
DEFAULT_MAILAPP = 'mozilla-thunderbird -compose'
|
||||
DEFAULT_FILE_MANAGER = 'xffm'
|
||||
|
||||
__options = {
|
||||
__options = ({
|
||||
# name: [ type, default_value, help_string ]
|
||||
'verbose': [ opt_bool, False, '', True ],
|
||||
'autopopup': [ opt_bool, False ],
|
||||
|
@ -301,7 +301,7 @@ class Config:
|
|||
'show_affiliation_in_groupchat': [opt_bool, True, _('If True, Gajim will show affiliation of groupchat occupants by adding a colored square to the status icon')],
|
||||
'global_proxy': [opt_str, '', _('Proxy used for all outgoing connections if the account does not have a specific proxy configured')],
|
||||
'ignore_incoming_attention': [opt_bool, False, _('If True, Gajim will ignore incoming attention requestd ("wizz").')],
|
||||
}
|
||||
}, {})
|
||||
|
||||
__options_per_key = {
|
||||
'accounts': ({
|
||||
|
@ -537,9 +537,9 @@ class Config:
|
|||
_('Tor'): ['socks5', 'localhost', 9050],
|
||||
}
|
||||
|
||||
def foreach(self, cb, data = None):
|
||||
for opt in self.__options:
|
||||
cb(data, opt, None, self.__options[opt])
|
||||
def foreach(self, cb, data=None):
|
||||
for opt in self.__options[1]:
|
||||
cb(data, opt, None, self.__options[1][opt])
|
||||
for opt in self.__options_per_key:
|
||||
cb(data, opt, None, None)
|
||||
dict_ = self.__options_per_key[opt][1]
|
||||
|
@ -553,7 +553,7 @@ class Config:
|
|||
Tree-like interface
|
||||
"""
|
||||
if node is None:
|
||||
for child, option in self.__options.iteritems():
|
||||
for child, option in self.__options[1].iteritems():
|
||||
yield (child, ), option
|
||||
for grandparent in self.__options_per_key:
|
||||
yield (grandparent, ), None
|
||||
|
@ -609,35 +609,44 @@ class Config:
|
|||
return None
|
||||
|
||||
def set(self, optname, value):
|
||||
if optname not in self.__options:
|
||||
if optname not in self.__options[1]:
|
||||
# raise RuntimeError, 'option %s does not exist' % optname
|
||||
return
|
||||
opt = self.__options[optname]
|
||||
value = self.is_valid(opt[OPT_TYPE], value)
|
||||
value = self.is_valid(self.__options[0][optname][OPT_TYPE], value)
|
||||
if value is None:
|
||||
# raise RuntimeError, 'value of %s cannot be None' % optname
|
||||
return
|
||||
|
||||
opt[OPT_VAL] = value
|
||||
self.__options[1][optname] = value
|
||||
|
||||
def get(self, optname = None):
|
||||
def get(self, optname=None):
|
||||
if not optname:
|
||||
return self.__options.keys()
|
||||
if optname not in self.__options:
|
||||
return self.__options[1].keys()
|
||||
if optname not in self.__options[1]:
|
||||
return None
|
||||
return self.__options[optname][OPT_VAL]
|
||||
return self.__options[1][optname]
|
||||
|
||||
def get_default(self, optname):
|
||||
if optname not in self.__options[0]:
|
||||
return None
|
||||
return self.__options[0][optname][OPT_VAL]
|
||||
|
||||
def get_type(self, optname):
|
||||
if optname not in self.__options[0]:
|
||||
return None
|
||||
return self.__options[0][optname][OPT_TYPE][0]
|
||||
|
||||
def get_desc(self, optname):
|
||||
if optname not in self.__options:
|
||||
if optname not in self.__options[0]:
|
||||
return None
|
||||
if len(self.__options[optname]) > OPT_DESC:
|
||||
return self.__options[optname][OPT_DESC]
|
||||
if len(self.__options[0][optname]) > OPT_DESC:
|
||||
return self.__options[0][optname][OPT_DESC]
|
||||
|
||||
def get_restart(self, optname):
|
||||
if optname not in self.__options:
|
||||
if optname not in self.__options[0]:
|
||||
return None
|
||||
if len(self.__options[optname]) > OPT_RESTART:
|
||||
return self.__options[optname][OPT_RESTART]
|
||||
if len(self.__options[0][optname]) > OPT_RESTART:
|
||||
return self.__options[0][optname][OPT_RESTART]
|
||||
|
||||
def add_per(self, typename, name): # per_group_of_option
|
||||
if typename not in self.__options_per_key:
|
||||
|
@ -648,7 +657,9 @@ class Config:
|
|||
if name in opt[1]:
|
||||
# we already have added group name before
|
||||
return 'you already have added %s before' % name
|
||||
opt[1][name] = copy.deepcopy(opt[0])
|
||||
opt[1][name] = {}
|
||||
for o in opt[0]:
|
||||
opt[1][name][o] = opt[0][o][OPT_VAL]
|
||||
|
||||
def del_per(self, typename, name, subname = None): # per_group_of_option
|
||||
if typename not in self.__options_per_key:
|
||||
|
@ -676,36 +687,50 @@ class Config:
|
|||
if subname not in obj:
|
||||
# raise RuntimeError, '%s is not a key of %s' % (subname, obj)
|
||||
return
|
||||
subobj = obj[subname]
|
||||
value = self.is_valid(subobj[OPT_TYPE], value)
|
||||
typ = self.__options_per_key[optname][0][subname][OPT_TYPE]
|
||||
value = self.is_valid(typ, value)
|
||||
if value is None:
|
||||
# raise RuntimeError, '%s of %s cannot be None' % optname
|
||||
return
|
||||
subobj[OPT_VAL] = value
|
||||
obj[subname] = value
|
||||
|
||||
def get_per(self, optname, key = None, subname = None): # per_group_of_option
|
||||
def get_per(self, optname, key=None, subname=None): # per_group_of_option
|
||||
if optname not in self.__options_per_key:
|
||||
return None
|
||||
dict_ = self.__options_per_key[optname][1]
|
||||
if not key:
|
||||
return dict_.keys()
|
||||
if key not in dict_:
|
||||
if optname in self.__options_per_key \
|
||||
and subname in self.__options_per_key[optname][0]:
|
||||
return self.__options_per_key \
|
||||
[optname][0][subname][1]
|
||||
if subname in self.__options_per_key[optname][0]:
|
||||
return self.__options_per_key[optname][0][subname][1]
|
||||
return None
|
||||
obj = dict_[key]
|
||||
if not subname:
|
||||
return obj
|
||||
if subname not in obj:
|
||||
return None
|
||||
return obj[subname][OPT_VAL]
|
||||
return obj[subname]
|
||||
|
||||
def get_desc_per(self, optname, key = None, subname = None):
|
||||
def get_default_per(self, optname, subname):
|
||||
if optname not in self.__options_per_key:
|
||||
return None
|
||||
dict_ = self.__options_per_key[optname][1]
|
||||
dict_ = self.__options_per_key[optname][0]
|
||||
if subname not in dict_:
|
||||
return None
|
||||
return dict_[subname][OPT_VAL]
|
||||
|
||||
def get_type_per(self, optname, subname):
|
||||
if optname not in self.__options_per_key:
|
||||
return None
|
||||
dict_ = self.__options_per_key[optname][0]
|
||||
if subname not in dict_:
|
||||
return None
|
||||
return dict_[subname][OPT_TYPE][0]
|
||||
|
||||
def get_desc_per(self, optname, key=None, subname=None):
|
||||
if optname not in self.__options_per_key:
|
||||
return None
|
||||
dict_ = self.__options_per_key[optname][0]
|
||||
if not key:
|
||||
return None
|
||||
if key not in dict_:
|
||||
|
@ -719,10 +744,10 @@ class Config:
|
|||
return obj[subname][OPT_DESC]
|
||||
return None
|
||||
|
||||
def get_restart_per(self, optname, key = None, subname = None):
|
||||
def get_restart_per(self, optname, key=None, subname=None):
|
||||
if optname not in self.__options_per_key:
|
||||
return False
|
||||
dict_ = self.__options_per_key[optname][1]
|
||||
dict_ = self.__options_per_key[optname][0]
|
||||
if not key:
|
||||
return False
|
||||
if key not in dict_:
|
||||
|
@ -749,8 +774,13 @@ class Config:
|
|||
|
||||
return (account not in no_log_for) and (jid not in no_log_for)
|
||||
|
||||
def _init_options(self):
|
||||
for opt in self.__options[0]:
|
||||
self.__options[1][opt] = self.__options[0][opt][OPT_VAL]
|
||||
|
||||
def __init__(self):
|
||||
#init default values
|
||||
self._init_options()
|
||||
for event in self.soundevents_default:
|
||||
default = self.soundevents_default[event]
|
||||
self.add_per('soundevents', event)
|
||||
|
|
|
@ -85,7 +85,6 @@ class OptionsParser:
|
|||
def write_line(self, fd, opt, parents, value):
|
||||
if value is None:
|
||||
return
|
||||
value = value[1]
|
||||
# convert to utf8 before writing to file if needed
|
||||
if isinstance(value, unicode):
|
||||
value = value.encode('utf-8')
|
||||
|
|
|
@ -723,7 +723,7 @@ class SignalObject(dbus.service.Object):
|
|||
for node in path:
|
||||
key += node + '#'
|
||||
key += name
|
||||
prefs_dict[DBUS_STRING(key)] = DBUS_STRING(value[1])
|
||||
prefs_dict[DBUS_STRING(key)] = DBUS_STRING(value)
|
||||
gajim.config.foreach(get_prefs)
|
||||
return prefs_dict
|
||||
|
||||
|
|
Loading…
Reference in New Issue