# HG changeset patch # User Jim Unroe # Date 1358631445 18000 # Node ID 810d80a586fd7a5a2a3875dc75489d71e5b801a5 # Parent d3fcca2f31731a41d7c79e86a059465b25f264ff [mq]: float_setting_callback_example.patch diff -r d3fcca2f3173 -r 810d80a586fd chirp/settings.py --- a/chirp/settings.py Sat Jan 19 14:51:54 2013 -0500 +++ b/chirp/settings.py Sat Jan 19 16:37:25 2013 -0500 @@ -28,16 +28,20 @@ def __init__(self): self._current = None self._has_changed = False + self._callback = lambda x: x def changed(self): """Returns True if the setting has been changed since init""" return self._has_changed + def set_callback(self, callback): + self._callback = callback + def set_value(self, value): """Sets the current value, triggers changed""" if self._current != None and value != self._current: self._has_changed = True - self._current = value + self._current = self._callback(value) def get_value(self): """Gets the current value""" @@ -81,6 +85,45 @@ """Returns the step increment""" return self._step +class RadioSettingValueFloat(RadioSettingValue): + """A floating-point setting""" + def __init__(self, minval, maxval, current, resolution=0.001, precision=5): + RadioSettingValue.__init__(self) + self._min = minval + self._max = maxval + self._res = resolution + self._pre = precision + self.set_value(current) + + def format(self, value=None): + """Formats the value into a string""" + if value is None: + value = self._current + fmt_string = "%%.%if" % self._pre + print fmt_string + return fmt_string % value + + def set_value(self, value): + try: + value = float(value) + except: + raise InvalidValueError("A floating point value is required") + if value > self._max or value < self._min: + raise InvalidValueError("Value %s not in range %s-%s" % ( + self.format(value), + self.format(self._min), self.format(self._max))) + + # FIXME: honor resolution + + RadioSettingValue.set_value(self, value) + + def get_min(self): + """Returns the minimum allowed value""" + return self._min + + def get_max(self): + """Returns the maximum allowed value""" + class RadioSettingValueBoolean(RadioSettingValue): """A boolean setting""" def __init__(self, current): diff -r d3fcca2f3173 -r 810d80a586fd chirp/uv5r.py --- a/chirp/uv5r.py Sat Jan 19 14:51:54 2013 -0500 +++ b/chirp/uv5r.py Sat Jan 19 16:37:25 2013 -0500 @@ -21,7 +21,8 @@ from chirp.settings import RadioSetting, RadioSettingGroup, \ RadioSettingValueInteger, RadioSettingValueList, \ RadioSettingValueList, RadioSettingValueBoolean, \ - RadioSettingValueString + RadioSettingValueString, RadioSettingValueFloat, \ + InvalidValueError MEM_FORMAT = """ #seekto 0x0008; @@ -944,6 +945,18 @@ STEP_LIST[self._memobj.vfob.step])) workmode.append(rs) + test = RadioSettingGroup("test", "test") + group.append(test) + def my_validate(value): + if value < 300 and value > 200: + raise InvalidValueError("Can't be between 200-300") + return value + + val = RadioSettingValueFloat(136, 450, 146.52) + val.set_callback(my_validate) + rs = RadioSetting("footest", "Foo Test", val) + test.append(rs) + return group def set_settings(self, settings): @@ -963,6 +976,8 @@ obj = _settings setting = element.get_name() print "Setting %s = %s" % (setting, element.value) + if setting == "footest": + return # This is a fake setting! setattr(obj, setting, element.value) except Exception, e: print element.get_name() diff -r d3fcca2f3173 -r 810d80a586fd chirpui/settingsedit.py --- a/chirpui/settingsedit.py Sat Jan 19 14:51:54 2013 -0500 +++ b/chirpui/settingsedit.py Sat Jan 19 16:37:25 2013 -0500 @@ -63,7 +63,12 @@ if self._top_setting_group is None: return - job = common.RadioJob(None, "set_settings", self._top_setting_group) + def setting_cb(result): + if isinstance(result, Exception): + common.show_error(_("Error in setting value: %s") % result) + + job = common.RadioJob(setting_cb, "set_settings", + self._top_setting_group) job.set_desc("Setting radio settings") self._rthread.submit(job) @@ -73,6 +78,8 @@ adj.configure(value.get_value(), value.get_min(), value.get_max(), value.get_step(), 1, 0) + elif isinstance(value, settings.RadioSettingValueFloat): + widget.set_text(value.format()) elif isinstance(value, settings.RadioSettingValueBoolean): widget.set_active(value.get_value()) elif isinstance(value, settings.RadioSettingValueList): @@ -89,9 +96,11 @@ print "Unsupported widget type %s for %s" % (value.__class__, element.get_name()) - def _save_setting(self, widget, value): + def _do_save_setting(self, widget, value): if isinstance(value, settings.RadioSettingValueInteger): value.set_value(widget.get_adjustment().get_value()) + elif isinstance(value, settings.RadioSettingValueFloat): + value.set_value(widget.get_text()) elif isinstance(value, settings.RadioSettingValueBoolean): value.set_value(widget.get_active()) elif isinstance(value, settings.RadioSettingValueList): @@ -105,6 +114,12 @@ self._save_settings() + def _save_setting(self, widget, value): + try: + self._do_save_setting(widget, value) + except settings.InvalidValueError, e: + common.show_error(_("Invalid setting value: %s") % e) + def _build_ui_group(self, group): def pack(widget, pos): self._table.attach(widget, pos, pos+1, self._index, self._index+1, @@ -139,6 +154,9 @@ widget = gtk.SpinButton() print "Digits: %i" % widget.get_digits() signal = "value-changed" + elif isinstance(value, settings.RadioSettingValueFloat): + widget = gtk.Entry() + signal = "focus-out-event" elif isinstance(value, settings.RadioSettingValueBoolean): widget = gtk.CheckButton(_("Enabled")) signal = "toggled" @@ -160,7 +178,11 @@ arraybox.pack_start(lalign, 1, 1, 1) widget.show() self._load_setting(value, widget) - widget.connect(signal, self._save_setting, value) + if signal == "focus-out-event": + widget.connect(signal, lambda w, e, v: + self._save_setting(w, v), value) + else: + widget.connect(signal, self._save_setting, value) self._index += 1