Commit 444bed27 authored by Yann Leboulanger's avatar Yann Leboulanger

ability to reset options to default value. Fixes #4465

parent 75c49597
<?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">&lt;b&gt;Description&lt;/b&gt;</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">&lt;b&gt;NOTE:&lt;/b&gt; 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[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[optname][OPT_VAL]
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
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment